所有工具类
最近碰到个需要下载zip压缩/解压缩包的需求,于是我在网上找了下别人写好的zip工具类。但找了好多篇博客,总是发现有bug。因此就自己来写了个工具类。
这个工具类的主要功能为:
(1)可以压缩/解压缩文件,也可以压缩/解压缩文件夹
(2)同时支持压缩多级文件夹,工具内部做了递归处理
(3)碰到空的文件夹,也可以压缩/解压缩
(4)可以选择是否保留原来的目录结构,如果不保留,所有文件跑压缩/解压缩包根目录去了,且空文件夹直接舍弃。注意:如果不保留文件原来目录结构,在碰到文件名相同的文件时,会压缩失败。
(5)代码中提供了压缩和解压缩文件的方法,可根据实际需求选择方法。
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.zhangjunbk.com">张军个人网站</a> <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) { } } } } }
zj.compress.bean.Compress
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.zhangjunbk.com">张军个人网站</a> <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; }
zj.compress.bean.CompressAttr
package zj.compress.bean; import java.io.Serializable; /** * 概况 :压缩文件属性操作<br> * * @version 1.00 (2011.12.02) * @author SHNKCS 张军 {@link <a target=_blank href="http://www.zhangjunbk.com">张军个人网站</a> <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; }
zj.compress.bean.Enums
/** * @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; } } }
本文为张军原创文章,转载无需和我联系,但请注明来自张军的军军小站,个人博客http://www.zhangjunbk.com