Java文件压缩与解压缩(二)
package com.cn;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.Enumeration;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import java.util.zip.ZipOutputStream;//错误小结://1 关于file.isFile()与file.isDirectory()记忆出了偏差.// 错误以为若是Directory一定是file,file不一定是Directory// 更正:file和Directory是两码事.只能是file或Directory中其中一个.// 要看的1 传入一个路径直接压缩了.//2 并不是说我们执行一句File f=new File("F:\\x.txt");// 在本地硬盘上就生成了一个x.txt文件.而应该进行如下的// 操作才可以.// File f=new File("F:\\x.txt");// if (!f.exists()) {// f.createNewFile();// }// 其中f.createNewFile()表示创建了一个空文件//// 多数的情况下,我们执行了File f=new File("F:\\x.txt")// 以后再利用输入流,输出流对f进行操作,比如往该x.txt文件中// 写入hello world// //3 血的教训:// zip()方法中没有关闭流zos.导致压缩后的文件解压时出错//重要总结://1 关于zip和unzip的核心操作对象是每一个文件!!!// 比如碰到一个directory,那么会去遍历里面的每一个文件,挨个对其进行压缩.// 不要错误地理解,若是一个directory,那么会将其作为一个整体进行压缩.//2 在JAVA中每一个压缩文件都用一个ZipEntry表示// 所以在压缩的过程中要得到每个文件的完整路径(从最外层文件夹至文件本身)// 用此完整路径为每个压缩文件new()一个ZipEntry//3 所以利用zipEntry可记录原来的目录层次.解压后才保持原样// 也可以看到在解压时利用entrys.hasMoreElements()来挨个// 解压每个zipEntry.// 参见解压中的代码:// new File(unzipPath+File.separator+entry.getName());public class TestZipAndUnZip { public static void main(String[] args) throws Exception { TestZipAndUnZip test=new TestZipAndUnZip(); //将某一个文件压缩成zip test.zip("F:\\", "kk\\cc.txt", "F:\\cc1.zip"); //将某一个zip解压 test.unZipFile("F:\\cc1.zip", "F:\\zzzz"); } /** * @param willZipDirPath 被压缩文件(目录)所在目录 * @param willZipFileName 被压缩文件(目录)的名称 * @param toFilePath 压缩后文件(目录)名 */public void zip(String willZipDirPath, String willZipFileName, String zipedFileName) {System.out.println("…………………以下为zip()方法…………………………");if (willZipDirPath == null) {return;}File willZipDir = new File(willZipDirPath);if (!willZipDir.exists() || !willZipDir.isDirectory()) {return;}// 获得目录绝对路径String willZipDirAbsolutePath = willZipDir.getAbsolutePath();System.out.println("willZipDir.getAbsolutePath()="+willZipDirAbsolutePath);//压缩后的文件File zipedFile = new File(zipedFileName);try {//从压缩后的文件得到压缩输出流ZipOutputStream//这里的zos只指向了压缩后文件的最外层.那么它怎么//维持了原来的目录结构呢?//就是利用了ZipEntry!!!//在fileToZip()方法中就可以看到ZipEntry的使用!!ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipedFile));if (willZipFileName.equals("*")) {//若传入的是*表示将此路径下所有东西都要压缩//所以调用dirToZip()dirToZip(willZipDirAbsolutePath, willZipDir, zos);} else {//将被压缩的文件File willZipFile = new File(willZipDirPath, willZipFileName);if (willZipFile.isFile()) {System.out.println("…………………最外层开始压缩文件………………………");fileToZip(willZipDirPath, willZipFile, zos);System.out.println("…………………最外层压缩文件结束………………………");}if (willZipFile.isDirectory()) {System.out.println("…………………最外层开始压缩目录………………………");dirToZip(willZipDirPath, willZipFile, zos);System.out.println("…………………最外层压缩目录结束………………………");}// 关闭流!!!zos.close();System.out.println("…………………以上为zip()方法…………………………");}} catch (Exception e) {// TODO: handle exception}} /** * @param dirPath 被压缩文件所在目录 * @param willZipFile 被压缩文件的名称 * @param zos 输出流 */public void fileToZip(String dirPath, File willZipFile,ZipOutputStream zos){ FileInputStream fis=null; ZipEntry zipEntry=null; byte [] buffer=new byte[1024*8]; int len=0; if (willZipFile.isFile()) {try {fis=new FileInputStream(willZipFile);zipEntry=new ZipEntry(getEntryName(dirPath, willZipFile));zos.putNextEntry(zipEntry);System.out.println("…………………以下为fileToZip()方法…………………………");System.out.println("zipEntry.getName="+zipEntry.getName());System.out.println("zipEntry.isDirectory="+zipEntry.isDirectory());System.out.println("zipEntry.getSize="+zipEntry.getSize());System.out.println("zipEntry.getTime="+zipEntry.getTime());System.out.println("zipEntry.getComment="+zipEntry.getComment());System.out.println("…………………以上为fileToZip()方法…………………………");while((len=fis.read(buffer))!=-1){zos.write(buffer, 0, len);}zos.closeEntry();fis.close();} catch (Exception e) {}} }/** * @param dirPath 被压缩目录所在的上级目录 * @param willZipDir 被压缩目录 * @param zos 输出流 */public void dirToZip(String dirPath, File willZipDir, ZipOutputStream zos) {if (willZipDir.isDirectory()) {File[] files = willZipDir.listFiles();//处理-->该文件夹下无文件 if (files.length==0) {ZipEntry zipEntry=new ZipEntry(getEntryName(dirPath, willZipDir));System.out.println("xxxxxxxxxxxxxxxx "+zipEntry.getName());try {zos.putNextEntry(zipEntry);//zos.closeEntry();} catch (Exception e) {e.printStackTrace();}return;} //处理-->该文件夹下的所有文件 for (int i = 0; i < files.length; i++) {File file = files[i];//若是文件,递归调用fileToZip()if (file.isFile()) {System.out.println("xxxxxxxxxx内层开始fileToZip()方法xxxxxxxxxx");fileToZip(dirPath, file, zos);System.out.println("xxxxxxxxxx内层fileToZip()方法结束xxxxxxxxxx");}//若是文件,递归调用dirToZip()if (file.isDirectory()) {System.out.println("xxxxxxxxxx内层开始dirToZip()方法xxxxxxxxxx");dirToZip(dirPath, file, zos);System.out.println("xxxxxxxxxx内层dirToZip()方法结束xxxxxxxxxx");}}}} /** * @param dirPath 将被压缩文件所在目录 * @param willZipFile 将被压缩的文件 * @return *///生成的是每个文件的完整路径(从最外层文件夹至文件本身)//这样生成的zipEntry就记录了原来的目录层次.解压后才保持原样public String getEntryName(String dirPath, File willZipFile) {if (!dirPath.endsWith(File.separator)) {dirPath += File.separator;}String willZipFilePath=willZipFile.getAbsolutePath();if (willZipFile.isDirectory()) {willZipFilePath+="/";}int index=willZipFilePath.indexOf(dirPath);System.out.println("xx返回的 entryName="+ willZipFilePath.substring(index+dirPath.length()));return willZipFilePath.substring(index+dirPath.length());}/** * @param zipedFileName 待解压zip文件 * @param unzipDirPath 文件解压后的最外层文件名 * @throws IOException */public void unZipFile(String zipedFileName,String unzipDirPath) throws Exception{if (!unzipDirPath.endsWith(File.separator)) {unzipDirPath+=File.separator;}try {ZipFile zipedFile=new ZipFile(zipedFileName);ZipEntry zipEntry=null;String entryName=null;String unzipedFileName=null;Enumeration entrys=zipedFile.entries();byte [] buffer=new byte[1024*8];int len=0;while (entrys.hasMoreElements()) {zipEntry=(ZipEntry) entrys.nextElement();entryName=zipEntry.getName();unzipedFileName=unzipDirPath+entryName;System.out.println("…………………以下为unZipFile()方法…………………………");System.out.println("zipedFileName="+zipedFileName);System.out.println("unzipDirPath="+unzipDirPath);System.out.println("entryName="+entryName);System.out.println("unzipedFileName="+unzipedFileName);System.out.println("…………………以上为unZipFile()方法…………………………");if (zipEntry.isDirectory()) {//没有执行此代码System.out.println("999999999999");new File(unzipedFileName).mkdirs();} else {//总是执行该代码.因为压缩的时候是对每个文件进行压缩的. new File(unzipedFileName).getParentFile().mkdirs();}FileOutputStream fos=null;InputStream is=null;File unzipedFile=new File(unzipedFileName);if (unzipedFile.isDirectory()) {File [] files=unzipedFile.listFiles();for (int i = 0; i < files.length; i++) {File file = files[i]; fos=new FileOutputStream(file); is=zipedFile.getInputStream(zipEntry);while ((len=is.read(buffer))!=-1) {fos.write(buffer, 0, len);}}}else{ fos=new FileOutputStream(unzipedFile); is=zipedFile.getInputStream(zipEntry); while ((len=is.read(buffer))!=-1) {fos.write(buffer, 0, len);}}//这里需要修改//fos.close();//is.close();}} catch (Exception e) {e.printStackTrace();}}}