使用Java API压缩和 解压缩数据

从ZIP文件解压并抽取数据

java.util.zip包提供了数据压缩和解压缩的类。解压ZIP文件实质是从输入流中读出数据。java.util.zip包提供了读取ZIP文件的ZipInputStream类。可以像任何其他输入流那样创建 ZipInputStream。例如,下列代码可用于创建输入流,以从ZIP文件格式中读出数据:

FileInputStream fis = new FileInputStream("figs.zip"); ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));

一旦打开ZIP输入流,就可以使用getNextEntry方法读取zip条目,该方法返回ZipEntry对象。如果到达文件末尾, getNextEntry就会返回零值:

ZipEntry entry; while((entry = zin.getNextEntry()) != null) { // extract data // open output streams }

现在创建解压缩输出流,如下:

int BUFFER = 2048; FileOutputStream fos = new FileOutputStream(entry.getName()); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);

注意: 在此节代码中,我们用 BufferedOutputStream代替了 ZIPOutputStreamZIPOutputStreamGZIPOutputStream使用大小为 512 的内部缓冲。 BufferedOutputStream的使用仅在缓冲的大小远远超过 512 时 (本例的设置为 2048)要予以调整。不过,在 ZIPOutputStream 的情况下,当 GZIPOutputStream不许设置缓冲区大小时,可以将内部缓冲区大小指定为设计参数。

在本节代码中,文件输出流是使用条目的名称创建的,该名称可以使用 entry.getName方法进行检索。然后,源压缩数据会读写到解压流:

while ((count = zin.read(data, 0, BUFFER)) != -1) { //System.out.write(x); dest.write(data, 0, count); }

最后,结束输入与输出流∶

dest.flush(); dest.close(); zin.close();

代码样本 1 中的源程序介绍了如何从 ZIP 文件中解压和提取文件。要测试 此样本,可对类进行编译,并通过传递 ZIP 格式的已压缩文件来进行运行:

prompt> java UnZip somefile.zip

注意,somefile.zip可以是任何ZIP兼容工具,如WinZip,创建的ZIP文件。

代码样本 1: UnZip.java

import java.io.*; import java.util.zip.*; public class UnZip { final int BUFFER = 2048; public static void main (String argv[]) { try { BufferedOutputStream dest = null; FileInputStream fis = new FileInputStream(argv[0]); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis)); ZipEntry entry; while((entry = zis.getNextEntry()) != null) { System.out.println("Extracting: " +entry); int count; byte data[] = new byte[BUFFER]; // write the files to the disk FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = zis.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); } zis.close(); } catch(Exception e) { e.printStackTrace(); } } }

重要的是,要注意ZipInputStream类是连续地读取ZIP文件的。不过,类ZipFile使用内部随机存取文件读取ZIP文件的内容,所以不必连续地读取ZIP文件的条目。


注意: ZIPInputStreamZipFile间的另一个基本区别是在高速缓存方面。在结合使用 ZipInputStreamFileInputStream读取文件时,Zip条目没有进行高速缓存。不过,如果文件是用 ZipFile(fileName)打开的,然后在内部进行高速缓存,那么,在 ZipFile(fileName)被再次调用时,该文件仅仅被打开一次。高速缓存值应用在第二次打开时。如果使用的是 UNIX,则值得注意的是,使用 ZipFile打开的全部ZIP文件都是内存映射的,因此 ZipFile的性能优越于 ZipInputStream。不过,如果相同ZIP文件的内容在程序执行期间要经常地进行更改和重新加载,那么使用 ZipInputStream效果更好。

下面是 ZIP 文件使用ZipFile类进行解压的方式:

  1. 创建ZipFile对象,方式是将待读取的ZIP文件指定为字符串文件名或 File 对象。

    ZipFile zipfile = new ZipFile("figs.zip");
  2. 使用条目方法,返回Enumeration对象,以循环通过文件全部的ZipEntry对象:
    while(e.hasMoreElements()) { entry = (ZipEntry) e.nextElement(); // read contents and save them }
  3. 通过将 ZipEntry传递到getInputStream的方式,读取 ZIP 文件内部具体的ZipEntry,它将返回可以读取条目内容的InputStream对象:
    is = new BufferedInputStream(zipfile.getInputStream(entry));


  4. 检索条目的文件名并创建输出流,以便保存:
    byte data[] = new byte[BUFFER]; FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = is.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); }
  5. 最后关闭所有输入与输出流∶
    dest.flush(); dest.close(); is.close();

完整的源程序如代码样本2所示。为测试该类,请再次进行编译和运行,方式是传递 ZIP 格式参数的文件。

prompt> java UnZip2 somefile.zip

代码样本2: UnZip2.java

import java.io.*; import java.util.*; import java.util.zip.*; public class UnZip2 { static final int BUFFER = 2048; public static void main (String argv[]) { try { BufferedOutputStream dest = null; BufferedInputStream is = null; ZipEntry entry; ZipFile zipfile = new ZipFile(argv[0]); Enumeration e = zipfile.entries(); while(e.hasMoreElements()) { entry = (ZipEntry) e.nextElement(); System.out.println("Extracting: " +entry); is = new BufferedInputStream (zipfile.getInputStream(entry)); int count; byte data[] = new byte[BUFFER]; FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = is.read(data, 0, BUFFER)) != -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); is.close(); } } catch(Exception e) { e.printStackTrace(); } } }

压缩和归档 ZIP 文件中的数据

ZipOutputStream可用于将数据压缩到ZIP文件。 ZipOutputStream以ZIP格式将数据写入输出流。创建ZIP文件的步骤很多。

  1. 第一步是创建ZipOutputStream对象,将向它传递希望写入文件的输出流。创建名为“myfigs.zip”的ZIP文件的方式是:
    FileOutputStream dest = new FileOutputStream("myfigs.zip"); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
  2. 一旦创建了目标压缩输出流,下一步就是打开源数据文件。本例中的源数据文件在当前目录中。列表命令用来获取当前目录文件的列表:
    File f = new File("."); String files[] = f.list(); for (int i=0; i<files.length; i++) { System.out.println("Adding: "+files[i]); FileInputStream fi = new FileInputStream(files[i]); // create zip entry // add entries to ZIP file }

    注意: 本代码样本能够压缩当前目录中的所有文件。它不处理子目录。作为训练,您可以修改代码样本 3,以处理子目录。


  3. 为被读取的每个文件创建压缩条目: ZipEntry entry = new ZipEntry(files[i]))
  4. 在向ZIP输出流写入数据之前,您必须首先使用out.putNextEntry(entry); 方法安置压缩条目对象∶ out.putNextEntry(entry);
  5. 向ZIP 文件写入数据∶
    int count; while((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); }
  6. 最后,结束输入与输出流∶
    origin.close(); out.close();

完整的源程序如代码样本 3 所示。

代码样本3: Zip.java

import java.io.*; import java.util.zip.*; public class Zip { static final int BUFFER = 2048; public static void main (String argv[]) { try { BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream("c:\\zip\\myfigs.zip"); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest)); //out.setMethod(ZipOutputStream.DEFLATED); byte data[] = new byte[BUFFER]; // get a list of files from current directory File f = new File("."); String files[] = f.list(); for (int i=0; i<files.length; i++) { System.out.println("Adding: "+files[i]); FileInputStream fi = new FileInputStream(files[i]); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(files[i]); out.putNextEntry(entry); int count; while((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } origin.close(); } out.close(); } catch(Exception e) { e.printStackTrace(); } } }

注意:条目可以添加到压缩(DEFLATED)或未压缩(STORED)表格中的 ZIP 文件里。 setMethod可用于设置存储的方法。例如,将方法设置为 DEFLATED (压缩),请使用: out.setMethod(ZipOutputStream.DEFLATED);将它设置为 STORED (非压缩),请使用:out.setMethod ( ZipOutputStream.STORED)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值