首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

Java文件压缩与解压缩(3)

2013-10-14 
Java文件压缩与解压缩(三)package com.cnimport java.io.Fileimport java.io.FileInputStreamimport ja

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("E:\\", "aa\\1.txt", "E:\\cc1.zip");      //将某一个目录压缩成zip   //test.zip("E:\\aa", "bb\\", "E:\\zz.zip");//right  //   test.zip("F:\\", "kk", "F:\\zz678910.zip");//right//////   //将某一个zip解压//   test.unZipFile("F:\\zz678910.zip", "E:\\zzzz");         /////////////////////以下正确///////////////////////////////   //压缩和解压单个文件   test.zip2("F:\\kk\\cc.txt","F:\\88.zip");   test.unZipFile2("F:\\88.zip", "F:\\abc");      //压缩和解压一个目录   test.zip2("F:\\kk","F:\\9zip.zip");   test.unZipFile2("F:\\9zip.zip", "F:\\9files");      /////////////////////以上正确//////////////////////////////   }   /** * @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));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();}}//////////////////////////////////////////////////////////////////////////////////////** * 该方法将一个给定路径的文件压缩 * @param willZipPath 待压缩文件的路径 * @param zipedPath   该文件压缩后的路径 */public void zip2(String willZipPath, String zipedPath) {try {File willZipFile = new File(willZipPath);File zipedFile = new File(zipedPath);ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipedFile));if (willZipFile.isFile()) {fileToZip2(willZipPath, zos);}if (willZipFile.isDirectory()) {dirToZip2(willZipPath, willZipFile, zos);}// 方法调用完成后关闭流zos.close();} catch (Exception e) {// TODO: handle exception}}/** * @param willZipFilePath  待压缩文件的路径 * @param zos              压缩文件输出流 * 1 关于以下两句代码 * ZipEntry entry = new ZipEntry(); * zos.putNextEntry(entry); * 把生成的ZipEntry对象加入到压缩文件中 * 之后往压缩文件中写入的内容均放在该ZipEntry对象中 *  * 2 fis.close()但是不能在此处zos.close() * 因为该zos是上一方法传递过来的.可能在压缩目录的时候会 * 再次使用到该zos流.若此时关闭,则导致目录中的一个文件 * 被压缩 */public void fileToZip2(String willZipFilePath,ZipOutputStream zos){try {File willZipFile=new File(willZipFilePath);ZipEntry entry = new ZipEntry(getEntryName2(willZipFilePath, willZipFile));zos.putNextEntry(entry);FileInputStream fis = new FileInputStream(willZipFilePath);int len = 0;while ((len = fis.read()) != -1){zos.write(len);}fis.close();//流关闭错误!//zos.close();} catch (Exception e) {}}/** * @param willZipDirctoryPath   原目录所在路径 * @param willZipedDirectory    原目录 * @param zos                   压缩流 * 注意: * 在处理空文件夹的时候 * getEntryName2(willZipDirctoryPath, willZipedDirectory)+"/" * 中的"/"是比不可少的 */public void dirToZip2(String willZipDirctoryPath,File willZipedDirectory, ZipOutputStream zos) {if (willZipedDirectory.isDirectory()) {File[] files = willZipedDirectory.listFiles();//处理空文件夹的情况            if (files.length==0) {ZipEntry zipEntry=new ZipEntry(getEntryName2(willZipDirctoryPath, willZipedDirectory)+"/");try {zos.putNextEntry(zipEntry);} 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(), zos);}//若是文件,递归调用dirToZip()if (file.isDirectory()) {dirToZip2(file.getAbsolutePath(),file, zos);}}}}/** * @param rawPath  需要压缩的目录或者文件的完整路径 * @param file     需要压缩的文件或者目录 * @return         entryName *  * 该方法返回EntryName,表示从最外层目录开始到该文件(目录) * 的完整路径 * 备注: * 1 该示例中文件均存放在某盘下,如E:\所以rawPath.substring(3); * 2 注释中"@param file 需要压缩的文件或者目录".其实绝大多数情况下 *  都是文件,只有一种情况是目录,就是空文件夹的情况.  */public String getEntryName2(String rawPath,File file){try {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      文件解压后的路径 * 对于文件或者目录操作的小梳理: * 1 对于目录应该先执行file.mkdir(s)()才可以 *  往里面其下存入文件.比如: *  File f=new File("F:\\test\\x.txt");if (!f.exists()) {f.createNewFile();}这当然要报错,因为x.txt的所在目录还不存在!!所以应该改正为:File f=new File("F:\\test\\x.txt");f.getParentFile().mkdirs();if (!f.exists()) {f.createNewFile();}2同样的道理File f=new File("F:\\test\\x.txt");if (f.isFile()) {System.out.println("true");}else{System.out.println("false");}结果为false3类似的问题File f=new File("F:\\x.txt");if (f.isFile()) {System.out.println("true");}else{System.out.println("false");}结果为false因为只是new了一个File,并没有创建!!!File f=new File("F:\\x.txt");f.createNewFile();if (f.isFile()) {System.out.println("true");}else{System.out.println("false");}此时为true此处:if (zipEntry.isDirectory()) {    new File(perUnzipFilePath).mkdirs();} else {new File(perUnzipFilePath).getParentFile().mkdirs();}已经建立了每个文件夹.然后才开始对每个空文件夹和每个文件进行流操作.和上面的道理一致,刚开始犯了个错误,没有采用else {fos = new FileOutputStream(perUnzipFile);is = zipFile.getInputStream(zipEntry);while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}}而是用if(perUnzipFile.isFile()){}来操作,这当然错了.因为该perUnzipFile没有执行perUnzipFile.createNewFile();所以它还不是File.类似的情况,多采用流操作来进行读写.所以总结两种与File有关的操作:1 File f=new File("");  f.createNewFile();     然后对f操作2 file f=new File("");    然后用输入输出流进行流操作    举例子:  File f=new File("F:\\2221x.txt");      FileOutputStream fos=new FileOutputStream(f);  String string="hello";  byte []b=string.getBytes();  fos.write(b, 0, b.length);     该例子是正确的.     疑问:没有执行 f.createNewFile()为什么不报错.因为输出流  FileOutputStream已经帮我们做了该工作了.修改例子即可知:File f=new File("F:\\2221x.txt");if (f.isFile()) {System.out.println("true1");} else {System.out.println("false1");}FileOutputStream fos=new FileOutputStream(f);if (f.isFile()) {System.out.println("true2");} else {System.out.println("false2");}String string="hello";byte []b=string.getBytes();fos.write(b, 0, b.length);输出false1,true2这就得到了验证. */public void unZipFile2(String zipedFilePath, String unzipPath) {FileOutputStream fos=null;InputStream is=null;ZipEntry zipEntry=null;String perUnzipFilePath=null;if (!unzipPath.endsWith(File.separator)) {unzipPath+=File.separator;}try {ZipFile zipFile=new ZipFile(zipedFilePath);Enumeration entries=zipFile.entries();byte [] buffer=new byte[1024*8];int len=0;while (entries.hasMoreElements()) {zipEntry = (ZipEntry) entries.nextElement();perUnzipFilePath = unzipPath + zipEntry.getName();//1建立每个文件夹if (zipEntry.isDirectory()) {//处理空文件夹的情况//创建空目录new File(perUnzipFilePath).mkdirs();} else {//为每个文件创立其所在目录new File(perUnzipFilePath).getParentFile().mkdirs();}                //2在用流操作处理每个文件夹中的文件// 2.1if中的操作只是针对空目录而进行的.所以if中的代码可以// 注释掉,无实际意义.// 2.2else中的操作是对于每个具体的文件而进行的流操作File perUnzipFile = new File(perUnzipFilePath);if (perUnzipFile.isDirectory()) {File[] files = perUnzipFile.listFiles();for (int i = 0; i < files.length; i++) {File file = files[i];fos = new FileOutputStream(file);is = zipFile.getInputStream(zipEntry);while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}}} else {fos = new FileOutputStream(perUnzipFile);is = zipFile.getInputStream(zipEntry);while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}}}if (fos!=null) {fos.close();}if (is!=null) {is.close();}} catch (Exception e) {e.printStackTrace();}}}


 

热点排行