ThinkJava-压缩

尽管存在许多种压缩算恙,但是Zip和GZIP可能是最常用的.因此我们可以很容易地使用多
种可读写这些格式的工具来操纵我们的压缩数据。
 
1 用GZIP进行简单压缩
GZIP接口非常简单, 因此如果我们只想对单个数据流(而不是一系列互异数据)进行压缩,
那么它可能是比较适合的选择。下面是对单个文件进行压缩的例子:
// {Args: GZIPcompress.java}
package com.java.io;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class GZIPcompress {
      public static void main(String[] args) throws IOException {
        if(args.length == 0) {
          System.out.println(
            "Usage: 
GZIPcompress file
" +
            "	Uses GZIP compression to compress " +
            "the file to test.gz");
          System.exit(1);
        }
        BufferedReader in = new BufferedReader(new FileReader(args[0]));
        BufferedOutputStream out = new BufferedOutputStream(
                                          new GZIPOutputStream(
                                            new FileOutputStream("test.gz")));
        System.out.println("Writing file");
        int c;
        while((c = in.read()) != -1){
            out.write(c);
        }
        in.close();
        out.close();
        System.out.println("Reading file");
        BufferedReader in2 = new BufferedReader(
                                  new InputStreamReader(new GZIPInputStream(
                                    new FileInputStream("test.gz"))));
        String s;
        while((s = in2.readLine()) != null){
            System.out.println(s);
        }
        in2.close();
      }
}
View Code
压缩类的使用非常直观一一直接将输出流封装成GZlPOutputStream或ZipOutputStream,并将
输入流封装成GZIPInputStream或ZipInputStream即可。其他全部操作就是通常的IO读写。这个例
子把面向字符的流和面向字节的流棍合了起来,输入(in ) 用Reader类,而GZIPOutputStream的
构造器只能接受OutputStream对象,不能接受Writer对象。在打开文件时, GZIPInputStream就会
被转换成Reader.
 

2.用Zip进行多文件保存
支持Zip格式的Java 库更加全面.利用该库可以方便地保存多个文件,它甚至有一个独立的
类,使得读取Zip文件更加方便.这个类库使用的是标准Zip格式,所以能与当前那些可通过因
特网下载的压缩工具很好地协作. 下面这个例子具有与前例相同的形式,但它能根据需要来处
理任意多个命令行参数。另外,它显示了用Checksum类来计算和校验文件的校验和的方法。
共有两利Checksum类型: Adler32 (它快一些) 和CRC32 (慢一些, 但更准确)。
// Uses Zip compression to compress any
// number of files given on the command line.
// {Args: ZipCompress.java}
package com.java.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import static com.java.util.Print.*;

public class ZipCompress {
    public static void main(String[] args) throws IOException {
        FileOutputStream f = new FileOutputStream("test.zip");
        CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
        ZipOutputStream zos = new ZipOutputStream(csum);
        BufferedOutputStream out = new BufferedOutputStream(zos);
        zos.setComment("A test of Java Zipping");
        
        // No corresponding getComment(), though.
        for(String arg : args) {
            print("Writing file " + arg);
            BufferedReader in = new BufferedReader(new FileReader(arg));
            zos.putNextEntry(new ZipEntry(arg));
            int c;
            while((c = in.read()) != -1){
                out.write(c);
            }
            in.close();
            out.flush();
        }
        out.close();
        
        // Checksum valid only after the file has been closed!
        print("Checksum: " + csum.getChecksum().getValue());
        
        // Now extract the files:
        print("Reading file");
        FileInputStream fi = new FileInputStream("test.zip");
        CheckedInputStream csumi = new CheckedInputStream(fi, new Adler32());
        ZipInputStream in2 = new ZipInputStream(csumi);
        BufferedInputStream bis = new BufferedInputStream(in2);
        ZipEntry ze;
        while((ze = in2.getNextEntry()) != null) {
            print("Reading file " + ze);
            int x;
            while((x = bis.read()) != -1){
                System.out.write(x);
            }
        }
        if(args.length == 1){
            print("Checksum: " + csumi.getChecksum().getValue());
        }
        bis.close();
        
        // Alternative way to open and read Zip files:
        ZipFile zf = new ZipFile("test.zip");
        Enumeration<? extends ZipEntry> e = zf.entries();
        while(e.hasMoreElements()) {
            ZipEntry ze2 = e.nextElement();
            print("File: " + ze2);
            // ... and extract the data as before
        }
    }
}
View Code
  对于每一个要加入压缩档案的文件,都必须调用putNextEntry() ,并将其传递给一个
ZlpEntry对象。ZipEntry对象包含了一个功能很广泛的接口,允许你获取和设置Zip文件内该特
定项上所有可利用的数据: 名字、压缩的和未压缩的文件大小、日期、CRC校验和、额外字段数
据、注释、压缩方法以及它是否是一个目录入口等等.然而,尽管Zip格式提供了设置密码的方
法.但Jav啪Zip类库并不提供这方面的支持。虽然CheckedlnputStream和CheckedOutputStream
都支持Adler32和CRC32两种类型的校验和,但是ZjpEntry类只有一个支持CRC的接口.虽然这
是一个底层Zip格式的限制,但却限制了人们不能使用速度更快的Adler32 .
  为了能够解压缩文件, ZiplnputStream提供了一个getNextEntry()方法返回下一个ZipEntry
(如果存在的话).。解压缩文件有一个更简便的方法一一利用ZipFile对象读取文件。该对象有一
个entries()方法用来向ZipEntries返回一个Enumeration (枚举).
  为了读取校验和,必须拥有对与之相关联的Checksum对象的访问权限。在这里保留了指向
CheckedOutputStream和CheckedlnputStream对象的引用.但是,也可以只保留一个指向Checksum对象的引用。
  Zip流中有一个令人困惑的方法setComment() . 正如前面ZipCompress.java中所示, 我们可
以在写文件时写注释,但却没有任何方法恢复ZiplnputStreaIn内的注释.似乎只能通过ZipEntry ,
才能以逐条方式完全支持注释的获取。
  当然, GZIP或Zip库的使用并不仅仅局限于文件一它可以压缩任何东西,包括需要通过网络发送的数据.

 3.

-----------

原文地址:https://www.cnblogs.com/tenWood/p/7475879.html