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.ZipInputStream;import java.util.zip.ZipOutputStream;//错误小结://1 关于file.isFile()与file.isDirectory()记忆出了偏差.// 错误以为若是Directory一定是file,file不一定是Directory// 更正:file和Directory是两码事.只能是file或Directory中其中一个.// 要看的1 传入一个路径直接压缩了.//2 血的教训:// zip()方法中没有关闭流zos.导致压缩后的文件解压时出错//重要总结://1 关于zip和unzip的核心操作对象是每一个文件!!!// 比如碰到一个directory,那么会去遍历里面的每一个文件,挨个对其进行压缩.// 不要错误地理解,若是一个directory,那么会将其作为一个整体进行压缩.//2 在JAVA中每一个压缩文件都用一个ZipEntry表示// 所以在压缩的过程中要得到每个文件的完整路径(从最外层文件夹至文件本身)// 用此完整路径为每个压缩文件new()一个ZipEntry//3 所以利用zipEntry可记录原来的目录层次.解压后才保持原样// 也可以看到在解压时利用entrys.hasMoreElements()来挨个// 解压每个zipEntrypublic class TestZipAndUnZip { public static void main(String[] args) throws Exception { TestZipAndUnZip test=new TestZipAndUnZip(); //将某一个文件压缩成zip// test.zip("E:\\", "aa\\1.txt", "E:\\cc1.zip"); //将某一个目录压缩成zip //test.zip("E:\\aa", "bb\\", "E:\\zz.zip");//right// // test.zip("E:\\", "aa", "E:\\zz678910.zip");//right//// //将某一个zip解压// test.unZipFile("E:\\zz.zip", "E:\\zzzz"); /////////////////////以下正确/////////////////////////////// //压缩和解压单个文件// test.zip2("E:\\aa\\1.txt","E:\\aaaaaaa\\aa1234.zip");// test.unZipFile2("E:\\aaaaaaa\\aa1234.zip", "E:\\aaaaaaa\\aaxixihaha"); //压缩和解压一个目录 test.zip2("D:\\developmentTools","E:\\20.zip"); test.unZipFile2("E:\\20.zip", "E:\\555aaxx99xxx"); /////////////////////以上正确////////////////////////////// } /** * @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);System.out.println("ccccccccccc name="+willZipFile.getName());System.out.println("ccccccccccc getAbsolutePath="+willZipFile.getAbsolutePath());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));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()) {//没有执行此代码new File(unzipedFileName).mkdirs();} else {//总是执行该代码.因为压缩的时候是对每个文件进行压缩的. new File(unzipedFileName).getParentFile().mkdirs();}File unzipedFile=new File(unzipedFileName);FileOutputStream fos=new FileOutputStream(unzipedFile);InputStream is=zipedFile.getInputStream(zipEntry);while ((len=is.read(buffer))!=-1) {fos.write(buffer, 0, len);}fos.close();is.close();}} catch (Exception e) {e.printStackTrace();}}//////////////////////////////////////////////////////////////////////////////////////** * 该方法将一个给定路径的文件压缩 * @param willZipPath 将要压缩的文件的路径 * @param zipedPath 该文件压缩后的路径 */public void zip2(String willZipPath,String zipedPath){try {File willZipedFile=new File(willZipPath);File zipedFile=new File(zipedPath);ZipOutputStream zos=new ZipOutputStream(new FileOutputStream(zipedFile));if (willZipedFile.isFile()) {fileToZip2(willZipPath,willZipedFile, zos);}if (willZipedFile.isDirectory()) {dirToZip2(willZipPath,willZipedFile, zos);}//方法调用完成后关闭流zos.close();} catch (Exception e) {// TODO: handle exception}}/** * @param rawPath * @param willZipedFile * @param zos */ //test.zip2("E:\\aa\\1.txt","E:\\aaaaaaa\\aa1234.zip");public void fileToZip2(String rawPath,File willZipedFile,ZipOutputStream zos){try {//实例化一个名称为ab.txt的ZipEntry对象File file=new File(rawPath);ZipEntry entry = new ZipEntry(getEntryName2(rawPath, file));//把生成的ZipEntry对象加入到压缩文件中//而之后往压缩文件中写入的内容都会放在这个ZipEntry对象里面zos.putNextEntry(entry);InputStream is = new FileInputStream(rawPath);int len = 0;while ((len = is.read()) != -1){zos.write(len);}is.close();//流关闭错误了!!//zos.close();} catch (Exception e) {}}/** * @param rawPath 原文件所在路径 * @param zipedFile 压缩后的文件 * @param zos */public void dirToZip2(String rawPath,File zipedFile, ZipOutputStream zos) {if (zipedFile.isDirectory()) {File[] files = zipedFile.listFiles();//处理-->该文件夹下无文件// if (files.length==0) {////ZipEntry zipEntry=new ZipEntry(getEntryName(dirPath, willZipDir));//ZipEntry zipEntry=new ZipEntry("");//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()) {fileToZip2(file.getAbsolutePath(),file, zos);}//若是文件,递归调用dirToZip()if (file.isDirectory()) {dirToZip2(file.getAbsolutePath(),file, zos);}}}}/** * @param rawPath 需要压缩的目录或者文件的完整路径 * @param file 需要压缩的文件 * @return entryName */public String getEntryName2(String rawPath,File file){//file是rawPath对应的filetry {String rawDir=rawPath.substring(3);int rawDirIndex=file.getAbsolutePath().indexOf(rawDir);String entryName=file.getAbsolutePath().substring(rawDirIndex);return entryName;} catch (Exception e) {}return null;}/** * @param zipedFilePath 原压缩文件的路径 * @param unzipPath 文件解压后的路径 */public void unZipFile2(String zipedFilePath, String unzipPath){try {//解压后的最外层文件夹File unzipFile=new File(unzipPath);if (!unzipFile.exists()) {unzipFile.mkdirs();}File zipedFile = new File(zipedFilePath);File perUnzipedFile = null;// 实例化ZipFile对象 这个很容易错!!!!// ZipFile zipFile = new ZipFile(file) ;ZipInputStream zis = new ZipInputStream(new FileInputStream(zipedFile));FileOutputStream fos = null; ZipEntry entry = null; while ((entry = zis.getNextEntry()) != null) { // 得到一个压缩实体perUnzipedFile = new File(unzipPath+File.separator+entry.getName());if (!perUnzipedFile.getParentFile().exists()) { perUnzipedFile.getParentFile().mkdirs(); // 创建父目录}if (!perUnzipedFile.exists()) { // 判断输出文件是否存在perUnzipedFile.createNewFile(); // 创建文件}// 得到每一个实体的输入流fos = new FileOutputStream(perUnzipedFile); int len = 0;while ((len = zis.read()) != -1) {fos.write(len);}}zis.close(); fos.close(); } catch (Exception e) {// TODO: handle exception}}}