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較好。