基于JDK API实现文件的压缩与解压
在实际开发过程中,会经常遇到下载附件或者导出报表的情况,有时候文件会比较多,用户更希望多个文件可以一起打包进行下载。这时就需要实现两部分功能:一部分是多个文件的打包处理,一部分是压缩文件的下载功能。
对于压缩文件的下载,可查看我的另一篇博文(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
上一篇: jvm memcache 问题(求助)
下一篇: 求怎样解决fsockopen函数,异常