在实际开发过程中,会经常遇到下载附件或者导出报表的情况,有时候文件会比较多,用户更希望多个文件可以一起打包进行下载。这时就需要实现两部分功能:一部分是多个文件的打包处理,一部分是压缩文件的下载功能。
对于压缩文件的下载,可查看我的另一篇博文(SpringMVC下打包文件的下载),本文主要提供多个文件的压缩与解压的例子。样例完全基于JDK自带的IO流处理类,主要相关类为ZipInputStream和ZipOutputStream,使用JDK API已经能够满足压缩与解压的需求。我看网上有不少提到压缩中文乱码的问题,建议用ant.jar中包的ZIP处理类进行处理,我进行了相关测试:使用JDK1.6进行压缩会出现压缩包中的文件中文名乱码,但是使用JDK1.7或者JDK1.8不会乱码。
所以本样例正常运行需要使用JDK1.7+的版本。
另注:本样例仍然有个问题有待解决:我分别使用txt文件、excel文件、word文件进行压缩测试,压缩正常,使用WinRAR工具解压后文件也能正常查看。但是使用JDK的IO流解压后,只有txt文件查看正常,excel与word文件都损坏了,无法正常查看。这个问题仍未找到原因与解决方案,若有大神告知,感激不尽。
下面直接上代码:
一、压缩与解压工具类
ZipUtils.java
package research.j2se.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* 使用JDK自带的Zip处理类进行文件的压缩与解压
*
*/
public class ZipUtils {
/**
* 压缩文件(一个或多个)到指定压缩包
*/
public static void zip( String targetFilePath, String ... sourceFilePaths){
if( sourceFilePaths == null || sourceFilePaths.length == 0 ){
return;
}
try {
File targetFile = new File(targetFilePath);
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetFile));
BufferedInputStream bis = null;
byte [] buffer = new byte[512];
for( int i = 0; i < sourceFilePaths.length; i++ ){
File sourceFile = new File(sourceFilePaths[i]);
if( sourceFile.exists() ){
//目标文件不存在则创建文件
if( ! targetFile.exists() ){
targetFile.createNewFile();
}
String sourceFileName = sourceFile.getName();
ZipEntry entry = new ZipEntry(sourceFileName);
//设置压缩包的入口
zos.putNextEntry(entry);
bis = new BufferedInputStream(new FileInputStream(sourceFile));
while( bis.read(buffer) != -1){
zos.write(buffer);
}
}
}
bis.close();
zos.flush();
zos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 解压文件到指定目录
*/
public static void unzip(String targetDirPath, String ... sourceFilePaths){
if( sourceFilePaths == null || sourceFilePaths.length == 0 ){
return;
}
//解压目录不存在则创建
File targetDir = new File(targetDirPath);
if( ! targetDir.exists() ){
targetDir.mkdirs();
}
try {
byte [] buffer = new byte[512];
for( int i = 0; i < sourceFilePaths.length; i++ ){
File sourceFile = new File(sourceFilePaths[i]);
ZipInputStream zis = new ZipInputStream(new FileInputStream(sourceFile));
ZipEntry entry = null;
//遍历压缩文件的各个入口
while( (entry=zis.getNextEntry()) != null ){
String fileName = entry.getName();
//创建对应的文件
File file = new File(targetDirPath+File.separator + fileName);
if( ! file.exists() ){
file.createNewFile();
}
//进行文件的写入
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file,true));
while( zis.read(buffer) != -1 ){
bos.write(buffer);
}
zis.closeEntry();
bos.flush();
bos.close();
}
zis.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch( Exception e ){
e.printStackTrace();
}
}
}
二、压缩与解压测试类
JdkZipUtilsTest.java
package research.j2se.io;
import junit.framework.TestCase;
import research.j2se.io.ZipUtils;
/**
* jdk压缩解压工具类测试
*/
public class JdkZipUtilsTest
extends TestCase
{
/**
* 测试压缩文件
*/
public void testZip()
{
String targetFilePath = "src/main/resources/ziptarget/zip/压缩.zip";
String sourceFilePath1 = "src/main/resources/zipsource/unzip/测试1.xlsx";
String sourceFilePath2 = "src/main/resources/zipsource/unzip/测试2.txt";
String sourceFilePath3 = "src/main/resources/zipsource/unzip/测试3.docx";
ZipUtils.zip(targetFilePath, sourceFilePath1,sourceFilePath2,sourceFilePath3);
}
/**
* 测试解压文件(这里Excel文件解压无法打开,使用解压工具可以打开)
*/
public void testUnzip(){
String targetDirPath = "src/main/resources/ziptarget/unzip";
String sourceFilePath1 = "src/main/resources/zipsource/zip/压缩.zip";
ZipUtils.unzip(targetDirPath, sourceFilePath1);
}
}
本样例测试通过。若要查看完整源码,可访问:https://github.com/wdmcygah/research-J2SE.git