所有工具类
最近碰到个需要下载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

