主要用到apache的ant.jar,也可用jdk的相关类,但会有中文乱码问题。最重要的俩类是ZipFile和ZipEntry,前者将zip文件转为java对象,后者将zip文件中的条目文件转为java对象。
核心代码如下:
压缩代码:
ZipOutputStream zipOs = new ZipOutputStream(fos);
ZipEntry zipEntry = new ZipEntry("entryName");
zipOs.putNextEntry(zipEntry);
解压缩代码:
Enumeration<ZipEntry> entries = zipFile.getEntries();
ZipEntry zipEntry = entries.nextElement();
InputStream ins = zipFile.getInputStream(zipEntry);
需要注意的地方:
针对空文件夹需要特殊处理,需要往Entry中放入”/“+文件夹名+“/“项
zipOs.putNextEntry("/");
详细点的练习:
/**
* 测试文件压缩与解压缩
*
*/
public class TestZip {
public static void main(String[] args) {
//-->压缩单个文件
zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst\\新建文本文档.zip", "D:\\BIZFLOW\\src\\tst\\新建文本文档.txt");
//-->压缩文件夹
//zipSingleFileOrFolder("D:\\BIZFLOW\\src\\tst.zip", "D:\\BIZFLOW\\src\\tst");
//-->压缩多个文件(不指定压缩文件保存路径)
//zipMultiFiles("","D:\\BIZFLOW\\src\\tst\\新建文本文档.txt","D:\\BIZFLOW\\src\\tst\\新建文本文档 - 副本.txt");
//-->压缩多个文件(指定压缩文件保存路径)
//zipMultiFiles("D:\\BIZFLOW\\src\\tst\\新建.zip","D:\\BIZFLOW\\src\\tst\\新建文本文档.txt","D:\\BIZFLOW\\src\\tst\\新建文本文档 - 副本.txt");
//-->解压缩文件
//unzipFile("D:\\BIZFLOW\\src\\tst\\新建", "D:\\BIZFLOW\\src\\tst\\新建文本文档.txt等.zip");
}
/**
* 压缩单个文件/文件夹
* @param destPath 压缩文件保存路径(为空串/null时默认压缩路径:待压缩文件所在目录,压缩文件名为待压缩文件/文件夹名+“等.zip”)
* @param srcPath 待压缩的文件路径
*/
public static void zipSingleFileOrFolder(String destPath, String srcPath) {
if(StringUtils.isBlank(srcPath)) {
throw new RuntimeException("待压缩文件夹不可为空!");
}
if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {
throw new RuntimeException("保存文件名应以.zip结尾!");
}
File file = new File(srcPath);
if(!file.exists()) {
throw new RuntimeException("路径'"+srcPath+"'下未找到文件");
}
if(file.isDirectory()) {
//压缩文件夹
zipFolder(destPath, srcPath);
} else {
//压缩单个文件
zipFile(destPath, srcPath);
}
}
/**
* 压缩多个文件
* @param destPath 压缩文件保存路径(为空串/null时默认压缩路径:待压缩文件所在目录,压缩文件名为第一个待压缩文件名+“等.zip”)
* @param srcPaths 待压缩文件路径集合
*/
public static void zipMultiFiles(String destPath, String...srcPaths) {
if(srcPaths==null || srcPaths.length==0) {
throw new RuntimeException("待压缩文件夹不可为空!");
}
if(StringUtils.isNotBlank(destPath) && !destPath.endsWith(".zip")) {
throw new RuntimeException("保存文件名应以.zip结尾!");
}
zipFiles(destPath, srcPaths);
}
/**
* 解压缩文件
* @param destPath 解压缩路径(为空串/null时默认解压缩路径:压缩文件所在目录)
* @param zipPath 压缩文件路径
*/
public static void unzipFile(String destPath, String zipPath) {
if(StringUtils.isBlank(zipPath)) {
throw new RuntimeException("压缩文件路径不可为空!");
}
if(!zipPath.endsWith(".zip")) {
throw new RuntimeException("保存文件名应以.zip结尾!");
}
File file = new File(zipPath);
if(StringUtils.isBlank(destPath)) {
destPath = getUnzipBasePath(file);
}
if(!file.exists()) {
throw new RuntimeException("路径'"+zipPath+"'下未找到文件");
}
ZipFile zipFile;
int len;
byte[] buff = new byte[1024];
try {
zipFile = new ZipFile(zipPath);
//获取压缩文件中所有条目
Enumeration<ZipEntry> entries = zipFile.getEntries();
if(entries!=null) {
while(entries.hasMoreElements()) {
//压缩文件条目转为文件或文件夹
ZipEntry zipEntry = entries.nextElement();
//获取输入流
InputStream ins = zipFile.getInputStream(zipEntry);
BufferedInputStream bis = new BufferedInputStream(ins);
File unzipFile = new File(destPath+File.separator+zipEntry.getName());
if(zipEntry.isDirectory()) {
unzipFile.mkdirs();
continue;
}
File pf = unzipFile.getParentFile();
if(pf!=null && !pf.exists()) {
pf.mkdirs();
}
unzipFile.createNewFile();
FileOutputStream fos = new FileOutputStream(unzipFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//输出流写文件
while((len=bis.read(buff, 0, 1024))!=-1) {
bos.write(buff, 0, len);
}
bos.flush();
fos.close();
bos.close();
}
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/**
* 获取解压缩文件基路径
* @param zipPath
* @return
*/
private static String getUnzipBasePath(File zipPath) {
return zipPath.getParentFile().getAbsolutePath();
}
/**
* 压缩单个文件
* @param destPath 压缩文件保存路径
* @param srcPath 待压缩文件路径
*/
private static void zipFile(String destPath, String srcPath) {
zipFiles(destPath, srcPath);
}
/**
* 压缩多个文件
* @param srcPath
* @param zipPath
*/
private static void zipFiles(String destPath, String...srcPaths) {
if(StringUtils.isBlank(destPath)) {
File srcFile0 = new File(srcPaths[0]);
destPath = srcFile0.getParentFile().getAbsolutePath()+File.separator+srcFile0.getName()+"等.zip";
}
File zipFile = new File(destPath);
FileOutputStream fos = null;
try {
zipFile.createNewFile();
zipFile.mkdirs();
fos = new FileOutputStream(zipFile);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
//获取输出流
ZipOutputStream zipOs = new ZipOutputStream(fos);
//循环将多个文件转为压缩文件条目
for(String srcPath : srcPaths) {
if(StringUtils.isBlank(srcPath)) {
throw new RuntimeException("待压缩文件路径不可为空!");
}
File srcFile = new File(srcPath);
try {
ZipEntry zipEntry = new ZipEntry(srcFile.getName());
zipOs.putNextEntry(zipEntry);
//获取输入流
FileInputStream fis = new FileInputStream(srcFile);
int len;
byte[] buff = new byte[1024];
//输入/输出流对拷
while((len=fis.read(buff))!=-1) {
zipOs.write(buff, 0, len);
}
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
try {
zipOs.flush();
zipOs.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/**
* 压缩文件夹
* @param destPath 压缩文件保存路径
* @param srcPath 待压缩文件夹路径
*/
private static void zipFolder(String destPath, String srcPath) {
File srcFile = new File(srcPath);
//如压缩文件保存路径为空,则默认保存路径
if(StringUtils.isBlank(destPath)) {
destPath = srcFile.getParent()+File.separator+srcFile.getName()+".zip";
}
FileOutputStream fos = null;
ZipOutputStream zipOs = null;
try {
fos = new FileOutputStream(destPath);
zipOs = new ZipOutputStream(fos);
//递归往压缩文件中添加文件夹条目
zipFolder(srcFile, srcFile, zipOs);
zipOs.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
throw new RuntimeException();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/**
* 递归往压缩文件中添加文件夹条目
* @param srcFile 待压缩文件夹路径
* @param baseFile
* @param zipOs
*/
private static void zipFolder(File srcFile, File baseFile, ZipOutputStream zipOs) {
int len;
byte[] buff = new byte[1024];
if(srcFile.isDirectory()) {
//针对空文件夹需要特殊处理,需要往Entry中放入"/"+文件夹名+"/"项
try {
zipOs.putNextEntry(new ZipEntry(srcFile.getAbsolutePath().replaceFirst(baseFile.getParentFile().getAbsolutePath().replaceAll("\\\\", "\\\\\\\\"), "")+"/"));
zipOs.closeEntry();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
//获取当前文件夹下文件列表
File[] fileLists = srcFile.listFiles();
if(fileLists!=null && fileLists.length>0) {
for (int i = 0; i < fileLists.length; i++) {
//递归往压缩文件中添加文件夹条目
zipFolder(fileLists[i], baseFile, zipOs);
}
}
} else {
//文件处理比较简单,直接放入Entry
try {
FileInputStream fis = new FileInputStream(srcFile);
zipOs.putNextEntry(new ZipEntry(getRelativePath(baseFile.getAbsolutePath(), srcFile)));
while((len=fis.read(buff))!=-1) {
zipOs.write(buff, 0, len);
}
zipOs.closeEntry();
fis.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
/**
* 获取相对基路径的相对路径
* @param basePath
* @param file
* @return
*/
private static String getRelativePath(String basePath, File file) {
if(!basePath.equalsIgnoreCase(file.getAbsolutePath())) {
return getRelativePath(basePath, file.getParentFile())+File.separator+file.getName();
} else {
return file.getName();
}
}
}