Java中的I/O支持读写压缩格式的数据流,我们可以对其进行封装以达到压缩和解压缩的目的。
这些类并不是从Reader、Writer继承来的,而是属于InputStream、OutputStream继承体系的一部分。也就是说他们面向的是对字节的操作。如果我们必须面向字符进行操作,可以使用InputStreamReader、OutputStreamWriter进行很方便的转换。
压缩类 | 功能 |
---|---|
CheckedInputStream | GetCheckSum()为任何inputStream产生校验和 |
CheckOutputStream | GetCheckSum()为任何Outputstream产生校验和 |
DeflaterOutputStream | 压缩类的基类 |
ZipOutputStream | DeflaterOutputStream的实现类,可以将数据流压缩为Zip格式的文件 |
GZIPOutputStream | DeflaterOutputStream的实现类,可以将数据流压缩为GZIP格式的文件 |
InflaterInputStream | 解压缩类的基类 |
ZipInputStream | InfalterInputStream的实现类,可以对Zip格式的文件进行解压缩 |
GZIPInputStream | InfalterInputStream的实现类,可以对Zip格式的文件进行解压缩 |
GZIP格式的压缩与解压缩
GZIP比较简单,适合对单个文件进行压缩和解压缩。
package com.mfs.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GZIPCompress {
/*
* 压缩
* 参数: file指定要压缩的文件,path指定压缩后的文件的存储路径
* 返回值:返回压缩后的文件的绝对路径
*/
public String compress(String file,String path) throws IOException {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(file)));
BufferedOutputStream out = new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(new File(path + "/GZIPCompress.gz"))));
byte[] b = new byte[1024];
int n = 0;
while ((n = in.read(b)) != -1) {
out.write(b, 0, n);
}
in.close();
out.close();
return new File(path + "/GZIPcompress.gz").getAbsolutePath();
}
/*
* 解压缩
* 参数: 要解压缩的目标文件
*/
public void deCompress (String file) throws FileNotFoundException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(new File(file))))); //使用InputStream把面向字节流的对象转换成面向字符流的对象
String s;
while ((s = in.readLine()) != null) {
System.out.println(s);
}
in.close();
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
GZIPCompress gz = new GZIPCompress();
String GZIPFile = gz.compress("src/com/mfs/io/GZIPCompress.java", "resource"); //将当前文件压缩压缩到本项目的resource文件夹下
gz.deCompress(GZIPFile); //解压缩压缩后的文件
}
}
Zip文件的压缩和解压缩
Zip有一个独立的类,所以包含的功能非常全面,它可以支持多个文件的压缩,压缩后的文件遵循标准的zip标准,所以很容易与市面上的压缩软件协同合作。
package com.mfs.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class ZipCompress {
/*
* 压缩
* 参数: file指定要压缩的文件,path指定压缩后的文件的存储路径
* 返回值:返回压缩后的文件的绝对路径
*/
public String compress (String[] file,String path) throws IOException {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(path + "/ZipCompress.zip")));
CheckedOutputStream csum = new CheckedOutputStream(zos, new Adler32()); //用于产生校验和,可以为任何InputStream产生校验和,有两种方法Adler32(快)、CRC32(慢,准确)
BufferedOutputStream out = new BufferedOutputStream(csum);
for (String f : file) {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(f)));
zos.putNextEntry(new ZipEntry(f)); //每次向压缩文件夹中加入新的文件必掉用putNextEntry()方法,参数为ZipEntry对象
int n = 0;
while ((n = in.read()) != -1) {
out.write(n);
}
in.close();
}
out.close();
//System.out.println(csum.getChecksum().getValue()); //校验和
return new File(path + "/ZipCompress.zip").getAbsolutePath();
}
/*
* 解压缩
* 参数: 要解压缩的目标文件
*/
public void deCompress (String file) throws IOException {
ZipInputStream zis = new ZipInputStream(new FileInputStream(new File(file)));
CheckedInputStream csum = new CheckedInputStream(zis, new Adler32()); //校验和
BufferedReader in = new BufferedReader(new InputStreamReader(csum));
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
String s;
while ((s = in.readLine()) != null) {
System.out.println(s);
}
}
//System.out.println(csum.getChecksum().getValue());
in.close();
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String[] file = new String[] {"src/com/mfs/io/ZipCompress.java","src/com/mfs/io/GZIPCompress.java"};
ZipCompress zip = new ZipCompress();
String zipFile = zip.compress(file, "resource");
zip.deCompress(zipFile);
}
}
对于每一个要加入压缩文件的文件,都必须调用putNextEntry(),并向其传递一个ZipEntry对象。ZipEntry对象包含了一个功能非常全面的接口,受用该对象,我们可以很方便的设置和使用压缩文件中对应文件的相关信息,如:名字、压缩的和未压缩的文件大小、日期、crc校验和(ZipEntry不支持Adler32)。
解压缩文件还有一个更简单的方法,那就是使用ZipFile类:
public void deCompress2 (String file) throws ZipException, IOException {
ZipFile zip = new ZipFile(new File(file));
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry ze = entries.nextElement();
BufferedReader in = new BufferedReader(new InputStreamReader(zip.getInputStream(ze)));
String s;
while ((s = in.readLine()) != null) {
System.out.println(s);
}
in.close();
}
}
Zip流中的setComment()方法可以增加一些注释,但是令人疑惑的是却没有任何获取注释的方法,如果我们想获取注释的话还是把注释放到ZipEntry较好。