最近在一个项目中需要对文件进行自动的解压缩,Java提供了这种支持,还是挺好用的。
工具包封装在java.util.zip中。
1.首先是多个文件压缩成一个ZIP文件
思路:用一个ZipOutputStream包装一个目的ZIP文件--->遍历文件数组:对每一个文件创建一个ZipEntry并put进ZipOutputStream中。读取当前文件的数据流写入ZipOutputStream中。
代码实现:
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.ZipOutputStream; /** *多文件压缩 *@author wxisme *@time 2015-9-24 下午5:13:32 */ public final class FilesToZip { private FilesToZip(){} /** * 压缩多个文件到一个zip文件中 * @param files 待压缩文件数组 * @param zipFilePath 压缩后的zip文件路径 * @param fileName zip文件的名字 * @return 是否成功 */ public static boolean fileToZip(File[] files,String zipFilePath,String fileName){ boolean flag = false; FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; ZipOutputStream zos = null; try { File zipFile = new File(zipFilePath + "/" + fileName +".zip"); if(zipFile.exists()) { zipFile.delete(); } File[] sourceFiles = files; fos = new FileOutputStream(zipFile); zos = new ZipOutputStream(new BufferedOutputStream(fos)); byte[] bufs = new byte[1024*10]; for(int i=0;i<sourceFiles.length;i++){ //创建ZIP实体,并添加进压缩包 ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName()); zos.putNextEntry(zipEntry); //读取待压缩的文件并写进压缩包里 fis = new FileInputStream(sourceFiles[i]); bis = new BufferedInputStream(fis, 1024*10); int read = 0; while((read=bis.read(bufs, 0, 1024*10)) != -1){ zos.write(bufs,0,read); } } flag = true; } catch (FileNotFoundException e) { e.printStackTrace(); throw new RuntimeException(e); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } finally{ //关闭流 try { if(null != bis) bis.close(); if(null != zos) zos.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } return flag; } }
2.对包含有文件夹的文件数组进行压缩
思路:遍历文件数组,判断是否是文件。如果是文件步骤同1,如果是文件夹(目录)则递归压缩这个文件夹。其他步骤和1类似。
代码实现:
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** *多文件夹压缩 *@author wxisme *@time 2015-9-24 下午7:36:06 */ public final class MultiZip { public static void ZipFiles(ZipOutputStream out,String path,File... srcFiles) { path = path.replaceAll("\*", "/"); if(!path.endsWith("/")){ path+="/"; } byte[] buf = new byte[1024]; try { for(int i=0;i<srcFiles.length;i++){ if(srcFiles[i].getName().endsWith(".zip")) { //防止形成死循环 continue; } if(srcFiles[i].isDirectory()){ File[] files = srcFiles[i].listFiles(); String srcPath = srcFiles[i].getName(); srcPath = srcPath.replaceAll("\*", "/"); if(!srcPath.endsWith("/")){ srcPath+="/"; } out.putNextEntry(new ZipEntry(path+srcPath)); ZipFiles(out,path+srcPath,files); } else{ FileInputStream in = new FileInputStream(srcFiles[i]); System.out.println(path + srcFiles[i].getName()); out.putNextEntry(new ZipEntry(path + srcFiles[i].getName())); int len; while((len=in.read(buf))>0){ out.write(buf,0,len); } out.closeEntry(); in.close(); } } } catch (Exception e) { e.printStackTrace(); } } public static void ZipFiles(File zip,String path,File... srcFiles) throws IOException { if(zip.exists()) { zip.delete(); } ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zip)); ZipFiles(out,path,srcFiles); out.close(); } }
3.解压
思路:获取压缩文件的ZipEntry,对每个ZipEntry进行恢复操作。创建同名文件获取数据流写入文件。
代码实现:
package com.wxisme.demo; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** *解压文件 *@author wxisme *@time 2015-10-5 下午9:18:57 */ public class Decompression { /** * 解压 * @param zipFilePath 待解压文件的路径 * @param unzipFilePath 解压后的文件存储路径 * @throws Exception */ public static void unzip(String zipFilePath, String unzipFilePath) throws Exception { File zipFile = new File(zipFilePath); //创建解压缩文件保存的路径 File unzipFileDir = new File(unzipFilePath); if (!unzipFileDir.exists() || !unzipFileDir.isDirectory()) { unzipFileDir.mkdirs(); } //开始解压 ZipEntry entry = null; String entryFilePath = null, entryDirPath = null; File entryFile = null, entryDir = null; int index = 0, count = 0; byte[] buffer = new byte[1024]; BufferedInputStream bis = null; BufferedOutputStream bos = null; ZipFile zip = new ZipFile(zipFile); Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>)zip.entries(); //循环对压缩包里的每一个文件进行解压 while(entries.hasMoreElements()) { entry = entries.nextElement(); //构建压缩包中一个文件解压后保存的文件全路径 entryFilePath = unzipFilePath + File.separator + entry.getName(); //构建解压后保存的文件夹路径 index = entryFilePath.lastIndexOf(File.separator); if (index != -1) { entryDirPath = entryFilePath.substring(0, index); } else { entryDirPath = ""; } entryDir = new File(entryDirPath); //如果文件夹路径不存在,则创建文件夹 if (!entryDir.exists() || !entryDir.isDirectory()) { entryDir.mkdirs(); } //创建解压文件 entryFile = new File(entryFilePath); if (entryFile.exists()) { //检测文件是否允许删除,如果不允许删除,将会抛出SecurityException SecurityManager securityManager = new SecurityManager(); securityManager.checkDelete(entryFilePath); //删除已存在的目标文件 entryFile.delete(); } //写入文件 bos = new BufferedOutputStream(new FileOutputStream(entryFile)); bis = new BufferedInputStream(zip.getInputStream(entry)); while ((count = bis.read(buffer, 0, 1024)) != -1) { bos.write(buffer, 0, count); } bos.flush(); bos.close(); } } }
注意:在压缩文件时,如果压缩路径包含要创建的zip文件就要注意逃过同名的zip文件,否则会造成死循环。