压缩、解压缩工具类

张军 3969 0

压缩、解压缩工具类

package zj.compress.util;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FilenameUtils;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand;

import de.innosystec.unrar.Archive;
import de.innosystec.unrar.rarfile.FileHeader;
import zj.check.util.CheckUtil;
import zj.common.KV;
import zj.common.exception.ServiceException;
import zj.compress.bean.CompressAttr;
import zj.compress.bean.Enums;
import zj.compress.bean.UnCompress;
import zj.io.util.FileUtil;
import zj.java.util.JavaUtil;

/**
 * 压缩、解压缩工具类
 * @version 1.00 (2011.12.02)
 * @author SHNKCS 张军 {@link <a target=_blank href="http://www.shanghaijiadun.com">上海加盾信息科技有限公司</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>}
 */
public class UnCompressUtil implements Serializable {
	// private static Logger logger = Logger.getLogger(Compress.class);
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 获取zip单个文件信息及内容
	 * 
	 * @param zipFile
	 *            压缩文件
	 * @return <文件名,内容byte[]>
	 */
	public static KV<String, byte[]> zipOnlyFile(File zipFile) {
		ZipInputStream zipInputStream = null;
		ByteArrayOutputStream bout = null;
		ZipEntry zipEntry = null;
		try {
			// logger.info("开始解压文件");
			bout = new ByteArrayOutputStream();
			// 获取zip文件流
			zipInputStream = new ZipInputStream(new FileInputStream(zipFile));
			// 获取压缩文件
			zipEntry = zipInputStream.getNextEntry();
			byte[] buffer = new byte[1024];
			int len = -1;
			while ((len = zipInputStream.read(buffer)) != -1) {
				bout.write(buffer, 0, len);
			}
			bout.flush();
			// 解压内容
			byte[] extraData = bout.toByteArray();
			// 压缩包内的文件名
			String zipEntryFileName = zipEntry.getName();
			return KV.with(zipEntryFileName, extraData);
		} catch (Exception e) {
			throw new ServiceException(e);
		} finally {
			if (zipInputStream != null) {
				try {
					zipInputStream.closeEntry();
				} catch (Exception e2) {
				}
				try {
					zipInputStream.close();
				} catch (Exception e) {
				}
			}
			if (bout != null) {
				try {
					bout.close();
				} catch (Exception e) {
				}
			}
		}
	}

	/**
	 * 解压zip格式压缩包 对应的是ant.jar
	 * 
	 * @param compress
	 *            压缩对象
	 * @throws Exception
	 */
	public static void unzip(UnCompress compress) {
		Project p = new Project();
		Expand e = new Expand();
		e.setProject(p);
		e.setSrc(new File(compress.srcPath));
		String overFlg = compress.overWrite;
		e.setOverwrite(Enums.OverWrite.OVER.getValue().equals(overFlg) ? true : false);
		e.setDest(new File(compress.descPath));
		/*
		 * ant下的zip工具默认压缩编码为UTF-8编码, 而winRAR软件压缩是用的windows默认的GBK或者GB2312编码 所以解压缩时要制定编码格式
		 */
		e.setEncoding(compress.encoding);
		e.execute();
	}

	/**
	 * 解压rar格式压缩包。 对应的是java-unrar-0.3.jar,但是java-unrar-0.3.jar又会用到commons-logging-1.1.1.jar
	 * 
	 * @param compress
	 *            压缩对象
	 * @throws Exception
	 */
	public static boolean unrarwin(UnCompress compress) {
		try {
			File srcFile = new File(compress.srcPath);
			if (!srcFile.exists()) {
				return false;
			}
			File destFile = new File(compress.descPath);
			if (!destFile.exists()) {
				destFile.mkdirs();
			}
			// 服务器需要安装winrar
			String winrarPath = compress.unrarPath;
			if (CheckUtil.isNull(winrarPath)) {
				winrarPath = "C:/Program Files/WinRAR/UnRAR.exe";
			}
			String cmd = winrarPath + " x " + srcFile.getAbsolutePath() + " " + destFile.getAbsolutePath();
			Process proc = Runtime.getRuntime().exec(cmd);
			if (proc.waitFor() != 0) {
				if (proc.exitValue() == 0) {
					return false;
				}
			} else {
			}
			return true;
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}

	/**
	 * 解压rar格式压缩包。 对应的是java-unrar-0.3.jar,但是java-unrar-0.3.jar又会用到commons-logging-1.1.1.jar
	 * 
	 * @param compress
	 *            压缩对象
	 * @throws Exception
	 */
	public static void unrar(UnCompress compress) {
		Archive arc = null;
		BufferedOutputStream bos = null;
		try {
			arc = new Archive(new File(compress.srcPath));
			FileHeader fh = arc.nextFileHeader();
			// 设置压缩文件里内容具体信息
			List<CompressAttr> attrs = compress.compressAttrs;
			while (fh != null) {
				// 1 根据不同的操作系统拿到相应的 destDirName 和 destFileName
				String compressFileName = JavaUtil.trim(fh.getFileNameString());
				// 设置目标文件/文件夹路径
				String descPath = compress.descPath + FileUtil.changePathSeparator(compressFileName);
				long length = fh.getFullUnpackSize();
				// //("目标文件路径:【" + descPath + "】压缩文件路径:【" + compressFileName + "】压缩文件大小:【" + length + "】");
				// 设置压缩文件里内容具体信息
				CompressAttr attr = new CompressAttr();
				attrs.add(attr);
				attr.descPath = compressFileName;
				attr.length = length;
				attr.directory = fh.isDirectory();
				// 取得文件名
				String[] compressFileNames = FileUtil.getFileNameExtension(compressFileName);
				// 文件名
				attr.fileName = compressFileNames[1] + compressFileNames[2];
				if (fh.isDirectory()) {
				} else {
					if (CheckUtil.isNotNull(compress.descPath)) {
						String[] descPaths = FileUtil.getFileNameExtension(descPath);
						File descFile = new File(descPath);
						if (Enums.OverWrite.OVER.getValue().equals(compress.overWrite)) {
							// 覆盖
							// //("【" + descPath + "】文件重名,系统自动覆盖此文件");
						} else {
							if (descFile.exists()) {
								if (Enums.OverWrite.NO_OVER.getValue().equals(compress.overWrite)) {
									// //("【" + descPath + "】文件重名,系统自动过虑此文件");
									fh = arc.nextFileHeader();
									continue;
								} else {
									String newPath = descPaths[0] + descPaths[1] + JavaUtil.getUUID() + descPaths[2];
									// //("【" + descPath + "】文件重名,系统自动重新命名:【" + newPath + "】");
									descFile = new File(newPath);
								}
							}
						}
						// 2创建文件夹
						File dir = new File(descPaths[0]);
						if (!dir.exists() || !dir.isDirectory()) {
							dir.mkdirs();
						}
						// 3解压缩文件
						FileOutputStream fos = new FileOutputStream(descFile);
						bos = new BufferedOutputStream(fos);
						arc.extractFile(fh, fos);
					}
				}
				fh = arc.nextFileHeader();
			}
		} catch (Exception e) {
			throw new ServiceException(e);
		} finally {
			if (arc != null) {
				try {
					arc.close();
					arc = null;
				} catch (Exception e) {
				}
			}
			if (bos != null) {
				try {
					bos.close();
					bos = null;
				} catch (Exception e) {
				}
			}
		}
	}

	/**
	 * 解压缩rar,zip
	 * 
	 * @param compress
	 *            压缩对象
	 * @throws Exception
	 */
	public static void setCompress(UnCompress compress) {
		try {
			/** 支持的文件扩展名 **/
			String srcType = FilenameUtils.getExtension(compress.srcPath);
			// 保证文件夹路径最后是"/"或者"\"
			if (CheckUtil.isNull(compress.descPath)) {
				compress.descPath = "";
				// //("压缩文件内容没有设置解压目录,因此系统将压缩文件内容读取至内存中");
			} else {
				compress.descPath = FileUtil.changePathSeparator(compress.descPath);
				if (!compress.descPath.endsWith(File.separator)) {
					compress.descPath = compress.descPath + File.separator;
				}
			}
			// 根据类型,进行相应的解压缩
			if (Enums.FileExtension.ZIP.getValue().equalsIgnoreCase(srcType)) {
				unzip(compress);
			} else if (Enums.FileExtension.RAR.getValue().equalsIgnoreCase(srcType)) {
				// unrar(compress);
				unrarwin(compress);
			} else {
				// //("只支持zip和rar格式的压缩包!");
				List<String> fes = new ArrayList<String>();
				for (Enums.FileExtension fe : Enums.FileExtension.values()) {
					fes.add(fe.getValue());
				}
				throw new ServiceException("只支持[" + Arrays.toString(fes.toArray()) + "]格式的压缩包!");
			}
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}
}

压缩文件

package zj.compress.bean;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;

/**
 * 概况 :压缩文件<br>
 * 
 * @version 1.00 (2011.12.02)
 * @author SHNKCS 张军 {@link <a target=_blank href="http://www.shanghaijiadun.com">上海加盾信息科技有限公司</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>}
 */
public class Compress implements Serializable {
	private static final long serialVersionUID = 1L;
	/** 源压缩文件路径,如果是目录,以/杠结尾,不添加此目录名,否则添加此目录名/文件路径 **/
	public Collection<String> srcPaths = new HashSet<String>();
	/** 目标压缩文件路径 **/
	public String descPath;
	/** 编码 **/
	public String encoding = "UTF-8";
	/** 是否覆盖 **/
	public String overWrite;
	/** 压缩文件根目录(多个目录用/隔开) **/
	public String destROOTName;
}

压缩文件属性操作

package zj.compress.bean;

import java.io.Serializable;

/**
 * 概况 :压缩文件属性操作<br>
 * 
 * @version 1.00 (2011.12.02)
 * @author SHNKCS 张军 {@link <a target=_blank href="http://www.shanghaijiadun.com">上海加盾信息科技有限公司</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>}
 */
public class CompressAttr implements Serializable {
	private static final long serialVersionUID = 1L;
	/** 压缩内文件路径 **/
	public String descPath;
	/** 文件大小 **/
	public long length;
	/** 是否是目录 **/
	public boolean directory;
	/** 文件名 **/
	public String fileName;
}

枚举压缩类型

/**
 * @Description  Encoding.java
 * @author 张军
 * @date 2018年9月18日 下午9:24:07
 * @version V1.0
 */
package zj.compress.bean;

/**
 * @author 张军
 * @date 2018年9月18日 下午9:24:07
 * @version V1.0
 */
/**
 * 枚举压缩类型
 * 
 * @author zhangjun
 * 
 */
public class Enums {
	/**
	 * 压缩文件扩展名
	 * 
	 * @author zhangjun
	 * 
	 */
	public static enum FileExtension {
		ZIP("zip", "zip"), RAR("rar", "rar");
		private final String value;
		private final String name;

		/**
		 * 获取值
		 * 
		 * @return 值
		 */
		public String getValue() {
			return value;
		}

		/**
		 * 获取名称
		 * 
		 * @return 名称
		 */
		public String getName() {
			return name;
		}

		/**
		 * 构造值-名称
		 * 
		 * @param value
		 *            值
		 * @param name
		 *            名称
		 */
		FileExtension(String value, String name) {
			this.value = value;
			this.name = name;
		}
	}

	/**
	 * ant下的zip工具默认压缩编码为UTF-8编码, 而winRAR软件压缩是用的windows默认的GBK或者GB2312编码 所以解压缩时要制定编码格式
	 * 
	 * @author zhangjun
	 * 
	 */
	public static enum Encoding {
		/**
		 * ASCII
		 */
		ASCII("ASCII", "ASCII"),
		/**
		 * MBCS
		 */
		MBCS("MBCS", "MBCS"),
		/**
		 * GB2312
		 */
		GB2312("GB2312", "GB2312"),
		/**
		 * GBK
		 */
		GBK("GBK", "GBK"),
		/**
		 * UNICODE
		 */
		UNICODE("UNICODE", "UNICODE"),
		/**
		 * UTF8
		 */
		UTF8("UTF-8", "UTF-8");
		private final String value;
		private final String name;

		/**
		 * 获取值
		 * 
		 * @return 值
		 */
		public String getValue() {
			return value;
		}

		/**
		 * 获取名称
		 * 
		 * @return 名称
		 */
		public String getName() {
			return name;
		}

		/**
		 * 构造值-名称
		 * 
		 * @param value
		 *            值
		 * @param name
		 *            名称
		 */
		Encoding(String value, String name) {
			this.value = value;
			this.name = name;
		}
	}
	
	/**
	 * 是否覆盖
	 * 
	 * @author zhangjun
	 * 
	 */
	public static enum OverWrite {
		DEFAULT("", "重复时重命名"), OVER("1", "覆盖"), NO_OVER("2", "不覆盖");
		private final String value;
		private final String name;

		/**
		 * 获取值
		 * 
		 * @return 值
		 */
		public String getValue() {
			return value;
		}

		/**
		 * 获取名称
		 * 
		 * @return 名称
		 */
		public String getName() {
			return name;
		}

		/**
		 * 构造值-名称
		 * 
		 * @param value
		 *            值
		 * @param name
		 *            名称
		 */
		OverWrite(String value, String name) {
			this.value = value;
			this.name = name;
		}
	}
}

解压缩文件

package zj.compress.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 概况 :解压缩文件<br>
 * 
 * @version 1.00 (2011.12.02)
 * @author SHNKCS 张军 {@link <a target=_blank href="http://www.shanghaijiadun.com">上海加盾信息科技有限公司</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>}
 */
public class UnCompress implements Serializable {
	private static final long serialVersionUID = 1L;
	/** 压缩文件中的属性对象集合 **/
	public List<CompressAttr> compressAttrs = new ArrayList<CompressAttr>();
	/** 压缩文件路径 **/
	public String unrarPath;
	/** 源压缩文件路径 **/
	public String srcPath;
	/** 解压目标压缩文件路径 **/
	public String descPath;
	/** 编码 **/
	public String encoding = "UTF-8";
	/** 是否覆盖{@link zj.compress.bean.Enums.OverWrite} **/
	public String overWrite;
}

压缩工具类

package zj.compress.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

import zj.check.util.CheckUtil;
import zj.common.exception.ServiceException;
import zj.compress.bean.Compress;
import zj.io.util.FileUtil;

/**
 * 压缩工具类
 * @version 1.00 (2011.12.02)
 * @author SHNKCS 张军 {@link <a target=_blank href="http://www.shanghaijiadun.com">上海加盾信息科技有限公司</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a>&nbsp;&nbsp;&nbsp;&nbsp;<a target=_blank href="http://user.qzone.qq.com/360901061/">张军QQ空间</a>}
 */
public class CompressUtil implements Serializable {
	// private static Logger logger = Logger.getLogger(Compress.class);
	private static final long serialVersionUID = 1L;

	/**
	 * 压缩文件夹/文件
	 * 
	 * @param bean
	 *            压缩对象
	 */
	public static void zip(Compress bean) {
		ZipOutputStream out = null;
		try {
			Collection<String> srcPaths = bean.srcPaths;
			String destPath = bean.descPath;
			String destEncoding = bean.encoding;
			if (srcPaths.size() == 0) {
				throw new ServiceException("源文件夹/文件必须设置【zj.compress.bean.Compress.srcPaths】");
			}
			if (CheckUtil.isNull(destPath)) {
				throw new ServiceException("目标文件【zj.compress.bean.Compress.destPath】");
			}
			String destRootName = bean.destROOTName;
			if (CheckUtil.isNull(destRootName)) {
				destRootName = "";
			} else {
				destRootName += "/";
			}
			// 压缩目标文件
			File destFile = new File(destPath);
			// 创建文件目录
			FileUtil.createFolderOrFile(destFile);
			// 创建压缩文件流
			out = new ZipOutputStream(destFile);
			// 设置压缩文件编码
			out.setEncoding(CheckUtil.isNull(destEncoding) ? "GBK" : destEncoding);
			// 开始循环文件压缩
			for (String srcPath : srcPaths) {
				srcPath = FileUtil.linuxSeparator(srcPath);
				File fileOrDirectory = new File(srcPath);
				if (fileOrDirectory.isDirectory()) {
					// 如果是目录
					if (srcPath.endsWith("/")) {
						// 不添加此目录名
						File[] entries = fileOrDirectory.listFiles();
						for (int i = 0; i < entries.length; i++) {
							// 递归压缩,更新curPaths
							zipFileOrDirectory(out, entries[i], destRootName, destPath, 0);
						}
					} else {
						// 添加目录名
						zipFileOrDirectory(out, fileOrDirectory, destRootName, destPath, 0);
					}
				} else {
					// 添加文件
					zipFileOrDirectory(out, fileOrDirectory, destRootName, destPath, 0);
				}
			}
		} catch (Exception e) {
			throw new ServiceException(e);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (IOException ex) {
				}
			}
		}
	}

	/**
	 * 递归压缩文件或目录
	 * 
	 * @param out
	 *            压缩输出流对象
	 * @param fileOrDirectory
	 *            要压缩的文件或目录对象
	 * @param curPath
	 *            当前压缩条目的路径,用于指定条目名称的前缀
	 * @throws IOException
	 */
	private static void zipFileOrDirectory(ZipOutputStream out, File fileOrDirectory, String curPath, String samePath, int byte_length) {
		FileInputStream in = null;
		try {
			if (!fileOrDirectory.isDirectory()) {
				// 压缩文件
				if (byte_length == 0)
					byte_length = 1024;
				byte[] buffer = new byte[byte_length];
				in = new FileInputStream(fileOrDirectory);
				boolean isExist = fileOrDirectory.getPath().equalsIgnoreCase(samePath);
				if (!isExist) {
					ZipEntry entry = new ZipEntry(curPath + fileOrDirectory.getName());
					// 设置压缩对象
					out.putNextEntry(entry);
					int bytes_read = -1;
					while ((bytes_read = in.read(buffer)) != -1) {
						out.write(buffer, 0, bytes_read);
					}
				}
				out.closeEntry();
			} else {
				// 压缩目录
				File[] entries = fileOrDirectory.listFiles();
				for (int i = 0; i < entries.length; i++) {
					// 递归压缩,更新curPaths
					zipFileOrDirectory(out, entries[i], curPath + fileOrDirectory.getName() + "/", samePath, byte_length);
				}
			}
		} catch (Exception e) {
			throw new ServiceException(e);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException ex) {
				}
			}
		}
	}
}



更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论