`

Java IO流 Zip文件的压缩和解压缩

阅读更多

最近在复习java的IO流,发现zip流这块还是空白,所以补补课,发现一片比较好的文档,所以转载了,出处:http://blog.csdn.net/hanshileiai/article/details/6718375?reload个人觉得写的比较好,其中的方法我也按照它的思路测试过,没有问题。

 

1、了解压缩流的主要作用

2、了解JAVA IO 支持的三种压缩格式

3、掌握ZipOutputStream、ZipFile、ZipInputStream 三个类的作用

具体内容

经常可以看见各种压缩文件:zip、jar、GZ、

正常情况下在IO 操作中,所有的类库都是在 IO 包中。

在实例化ZipEntry 的时候,要设置名称,此名称实际上就是压缩文件中每一个元素的名称。

1、ZipOutputStream

此类的功能就是完成ZIP格式输出的。

继承关系:

 

java.lang.Object
  
extended by
java.io.OutputStream
      
extended by
java.io.FilterOutputStream
          
extended by
java.util.zip.DeflaterOutputStream
              
extended by
java.util.zip.ZipOutputStream

 

从定义可以发现,就是一个字节的输出流。

 

public void putNextEntry(ZipEntry e)
                  throws IOException

在压缩文件中,每一个压缩的内容都可以用一个ZipEntry 表示,所以在进行压缩之前必须通过putNextEntry 设置一个ZipEntry 即可。

 

 

[java] view plaincopy
 
  1. import java.io.File ;  
  2. import java.io.FileInputStream ;  
  3. import java.io.InputStream ;  
  4. import java.util.zip.ZipEntry ;  
  5. import java.util.zip.ZipOutputStream ;  
  6. import java.io.FileOutputStream ;  
  7. public class ZipOutputStreamDemo01{  
  8.     public static void main(String args[]) throws Exception{    // 所有异常抛出  
  9.         File file = new File("d:" + File.separator + "mldn.txt") ;  // 定义要压缩的文件  
  10.         File zipFile = new File("d:" + File.separator + "mldn.zip") ;   // 定义压缩文件名称  
  11.         InputStream input = new FileInputStream(file) ; // 定义文件的输入流  
  12.         ZipOutputStream zipOut = null ; // 声明压缩流对象  
  13.         zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ;  
  14.         zipOut.putNextEntry(new ZipEntry(file.getName())) ; // 设置ZipEntry对象  
  15.         zipOut.setComment("www.mldnjava.cn") ;  // 设置注释  
  16.         int temp = 0 ;  
  17.         while((temp=input.read())!=-1){ // 读取内容  
  18.             zipOut.write(temp) ;    // 压缩输出  
  19.         }  
  20.         input.close() ; // 关闭输入流  
  21.         zipOut.close() ;    // 关闭输出流  
  22.     }  
  23. };  

以上的操作代码完成的只是一个文件的压缩,如果要完成一个文件夹呢?

 

[java] view plaincopy
 
  1. import java.io.File ;  
  2. import java.io.FileInputStream ;  
  3. import java.io.InputStream ;  
  4. import java.util.zip.ZipEntry ;  
  5. import java.util.zip.ZipOutputStream ;  
  6. import java.io.FileOutputStream ;  
  7. public class ZipOutputStreamDemo02{  
  8.     public static void main(String args[]) throws Exception{    // 所有异常抛出  
  9.         File file = new File("d:" + File.separator + "mldn") ;  // 定义要压缩的文件夹  
  10.         File zipFile = new File("d:" + File.separator + "mldndir.zip") ;    // 定义压缩文件名称  
  11.         InputStream input = null ;  // 定义文件输入流  
  12.         ZipOutputStream zipOut = null ; // 声明压缩流对象  
  13.         zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ;  
  14.         zipOut.setComment("www.mldnjava.cn") ;  // 设置注释  
  15.         int temp = 0 ;  
  16.         if(file.isDirectory()){ // 判断是否是文件夹  
  17.             File lists[] = file.listFiles() ;   // 列出全部文件  
  18.             for(int i=0;i<lists.length;i++){  
  19.                 input = new FileInputStream(lists[i]) ; // 定义文件的输入流  
  20.                 zipOut.putNextEntry(new ZipEntry(file.getName()  
  21.                     +File.separator+lists[i].getName())) ;  // 设置ZipEntry对象  
  22.                 while((temp=input.read())!=-1){ // 读取内容  
  23.                     zipOut.write(temp) ;    // 压缩输出  
  24.                 }  
  25.                 input.close() ; // 关闭输入流  
  26.             }  
  27.         }  
  28.         zipOut.close() ;    // 关闭输出流  
  29.     }  
  30. };  

3.2 ZipFile

 

是一个专门表示压缩文件的类。

ZipFile 在实例化的时候必须接收File 类的实例。此File 类的实例是指向一个压缩 *.zip 文件。

第一步:为 ZipFile 实例化

实例化时需要接收File  类的引用

[java] view plaincopy
 
  1. import java.io.File ;  
  2. import java.io.FileInputStream ;  
  3. import java.io.InputStream ;  
  4. import java.util.zip.ZipEntry ;  
  5. import java.util.zip.ZipOutputStream ;  
  6. import java.util.zip.ZipFile ;  
  7. import java.io.FileOutputStream ;  
  8. public class ZipFileDemo01{  
  9.     public static void main(String args[]) throws Exception{    // 所有异常抛出  
  10.         File file = new File("d:" + File.separator + "mldn.zip") ;  // 找到压缩文件  
  11.         ZipFile zipFile = new ZipFile(file) ;   // 实例化ZipFile对象  
  12.         System.out.println("压缩文件的名称:" + zipFile.getName()) ;    // 得到压缩文件的名称  
  13.     }  
  14. };  

通过ZipFile 文件,为mldn.zip 进行解压缩操作。

 

[java] view plaincopy
 
  1. import java.io.File ;  
  2. import java.io.FileInputStream ;  
  3. import java.io.InputStream ;  
  4. import java.util.zip.ZipEntry ;  
  5. import java.util.zip.ZipOutputStream ;  
  6. import java.io.FileOutputStream ;  
  7. public class ZipOutputStreamDemo02{  
  8.     public static void main(String args[]) throws Exception{    // 所有异常抛出  
  9.         File file = new File("d:" + File.separator + "mldn") ;  // 定义要压缩的文件夹  
  10.         File zipFile = new File("d:" + File.separator + "mldndir.zip") ;    // 定义压缩文件名称  
  11.         InputStream input = null ;  // 定义文件输入流  
  12.         ZipOutputStream zipOut = null ; // 声明压缩流对象  
  13.         zipOut = new ZipOutputStream(new FileOutputStream(zipFile)) ;  
  14.         zipOut.setComment("www.mldnjava.cn") ;  // 设置注释  
  15.         int temp = 0 ;  
  16.         if(file.isDirectory()){ // 判断是否是文件夹  
  17.             File lists[] = file.listFiles() ;   // 列出全部文件  
  18.             for(int i=0;i<lists.length;i++){  
  19.                 input = new FileInputStream(lists[i]) ; // 定义文件的输入流  
  20.                 zipOut.putNextEntry(new ZipEntry(file.getName()  
  21.                     +File.separator+lists[i].getName())) ;  // 设置ZipEntry对象  
  22.                 while((temp=input.read())!=-1){ // 读取内容  
  23.                     zipOut.write(temp) ;    // 压缩输出  
  24.                 }  
  25.                 input.close() ; // 关闭输入流  
  26.             }  
  27.         }  
  28.         zipOut.close() ;    // 关闭输出流  
  29.     }  
  30. };  

以上的操作中,有一个问题,必须知道压缩文件中的每一个压缩实体的名称才可以进行解压缩操作,而如果现在在假设是一个文件夹呢? 
3、ZipInputStream

 

定义:

java.lang.Object
  
extended by
java.io.InputStream
      
extended by
java.io.FilterInputStream
          
extended by
java.util.zip.InflaterInputStream
              
extended by
java.util.zip.ZipInputStream

 

[java] view plaincopy
 
  1. import java.io.File ;  
  2. import java.io.FileInputStream ;  
  3. import java.io.InputStream ;  
  4. import java.util.zip.ZipEntry ;  
  5. import java.util.zip.ZipInputStream ;  
  6. import java.io.FileInputStream ;  
  7. public class ZipInputStreamDemo01{  
  8.     public static void main(String args[]) throws Exception{    // 所有异常抛出  
  9.         File zipFile = new File("d:" + File.separator + "mldn.zip") ;   // 定义压缩文件名称  
  10.         ZipInputStream input = null ;   // 定义压缩输入流  
  11.         input = new ZipInputStream(new FileInputStream(zipFile)) ;  // 实例化ZIpInputStream  
  12.         ZipEntry entry = input.getNextEntry() ; // 得到一个压缩实体  
  13.         System.out.println("压缩实体名称:" + entry.getName()) ;  
  14.         input.close() ;  
  15.     }  
  16. };  

利用此特性并结合 ZipFile 就可以完成解压缩文件夹的功能。

 

ZipFile 对象,可以找到每一个ZipEntry 的输入流。但是ZipInputStream 并不能得到每一个输入流,所以需要使用ZipFile,但是ZipInputStream  在取得每一个ZipEntry 的时候,不需要每一个ZipEntry 的时候,不需要每一个ZipEntry 的名称。

[java] view plaincopy
 
  1. import java.io.File ;  
  2. import java.io.OutputStream ;  
  3. import java.io.InputStream ;  
  4. import java.util.zip.ZipEntry ;  
  5. import java.util.zip.ZipFile ;  
  6. import java.util.zip.ZipInputStream ;  
  7. import java.io.FileInputStream ;  
  8. import java.io.FileOutputStream ;  
  9. public class ZipInputStreamDemo02{  
  10.     public static void main(String args[]) throws Exception{    // 所有异常抛出  
  11.         File file = new File("d:" + File.separator + "mldndir.zip") ;   // 定义压缩文件名称  
  12.         File outFile = null ;   // 输出文件的时候要有文件夹的操作  
  13.         ZipFile zipFile = new ZipFile(file) ;   // 实例化ZipFile对象  
  14.         ZipInputStream zipInput = null ;    // 定义压缩输入流  
  15.         OutputStream out = null ;   // 定义输出流,用于输出每一个实体内容  
  16.         InputStream input = null ;  // 定义输入流,读取每一个ZipEntry  
  17.         ZipEntry entry = null ; // 每一个压缩实体  
  18.         zipInput = new ZipInputStream(new FileInputStream(file)) ;  // 实例化ZIpInputStream  
  19.         while((entry = zipInput.getNextEntry())!=null){ // 得到一个压缩实体  
  20.             System.out.println("解压缩" + entry.getName() + "文件。") ;  
  21.             outFile = new File("d:" + File.separator + entry.getName()) ;   // 定义输出的文件路径  
  22.             if(!outFile.getParentFile().exists()){  // 如果输出文件夹不存在  
  23.                 outFile.getParentFile().mkdir() ;   // 创建文件夹  
  24.             }  
  25.             if(!outFile.exists()){  // 判断输出文件是否存在  
  26.                 outFile.createNewFile() ;   // 创建文件  
  27.             }  
  28.             input = zipFile.getInputStream(entry) ; // 得到每一个实体的输入流  
  29.             out = new FileOutputStream(outFile) ;   // 实例化文件输出流  
  30.             int temp = 0 ;  
  31.             while((temp=input.read())!=-1){  
  32.                 out.write(temp) ;  
  33.             }  
  34.             input.close() ;     // 关闭输入流  
  35.             out.close() ;   // 关闭输出流  
  36.         }  
  37.         input.close() ;  
  38.     }  
  39. };  

如果目录不存在,则应该进行创建操作。

 

总结:

1、压缩文件中的每一个压缩实体都使用ZipEntry 保存,一个压缩文件中可能包含一个或多个的ZipEntry 对象。

2、在JAVA中可以进行zip、jar、gz、三种格式的压缩支持,操作流程基本上是一样的

3、ZipOutputStream 可以进行压缩输出,但是输出的位置不一定是文件。

4、ZipFile 表示每一个压缩文件,可以得到每一个压缩实体的输入流

5、ZipInputStream 可以得到每一个实体,但是却无法得到每一个实体的输入流。

 

附件为我个人测试用的代码,和文章中提到的方法和思路基本是一致的。

 

附加一段拷贝文件夹的代码:

 

package com.fit.test.io.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Test {

	private static void copy(File originalFile, File goalFile)
			throws IOException {

		if (!goalFile.exists()) {
			goalFile.mkdirs();
		}

		if (originalFile.isFile()) {
			copy(originalFile, new File(goalFile, originalFile.getName()));
		}
		if (originalFile.isDirectory()) {
			copyDirectory(originalFile, goalFile);
		}

	}

	private static void copyDirectory(File originalFile, File goalFile)
			throws IOException {

		File toInDir = new File(goalFile, originalFile.getName());

		toInDir.mkdir();

		File[] fileList = originalFile.listFiles();

		if (fileList == null || fileList.length == 0) {
			return;
		}

		for (int i = 0; i < fileList.length; i++) {
			if (fileList[i].isDirectory()) {
				copyDirectory(fileList[i], toInDir);
			} else if (fileList[i].isFile()) {
				copyFile(fileList[i], new File(toInDir, fileList[i].getName()));
			}
		}
	}

	private static void copyFile(File originalFile, File goalFile)
			throws IOException {

		FileInputStream fis = null;

		FileOutputStream fos = null;

		fis = new FileInputStream(originalFile);

		fos = new FileOutputStream(goalFile);

		int temp = -1;

		byte[] b = new byte[1024];

		while ((temp = fis.read(b)) != -1) {
			fos.write(b, 0, temp);
		}

		fos.flush();
		fos.close();
		fis.close();

	}

	public static void main(String[] args) throws IOException {

		File originalFile = new File("F:\\Work\\apache-ant-1.9.2-bin");

		File goalFile = new File("F:\\Work\\back");

		copy(originalFile, goalFile);

		System.out.println("拷贝完成");
		
		
	}
}

 

 

 

  • src.zip (2.8 KB)
  • 下载次数: 27
分享到:
评论
2 楼 飞出四季做的茧 2018-11-07  
kris_zhang 写道
int temp = 0 ; 
        while((temp=input.read())!=-1){ // 读取内容 
            zipOut.write(temp) ;    // 压缩输出 
        } 

这种方式我测试一下,发现速度非常慢,26M的文件花了31秒 。有方法提高压缩速度么?


byte[] tempBuf = new byte[1024];
int length;
while((length = input.read(tempBuf)) != -1) {
    zipOut.write(tempBuf, 0, length);
}
1 楼 kris_zhang 2017-06-30  
int temp = 0 ; 
        while((temp=input.read())!=-1){ // 读取内容 
            zipOut.write(temp) ;    // 压缩输出 
        } 

这种方式我测试一下,发现速度非常慢,26M的文件花了31秒 。有方法提高压缩速度么?

相关推荐

Global site tag (gtag.js) - Google Analytics