欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

利用JAVAAPI函數(shù)實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓縮(轉(zhuǎn))

本文通過(guò)對(duì)數(shù)據(jù)壓縮算法的簡(jiǎn)要介紹,然后以詳細(xì)的示例演示了利用java.util.zip包實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓,并擴(kuò)展到在網(wǎng)絡(luò)傳輸方面如何應(yīng)用java.util.zip包現(xiàn)數(shù)據(jù)壓縮與解壓
綜述

許多信息資料都或多或少的包含一些多余的數(shù)據(jù)。通常會(huì)導(dǎo)致在客戶(hù)端與服務(wù)器之間,應(yīng)用程序與計(jì)算機(jī)之間極大的數(shù)據(jù)傳輸量。最常見(jiàn)的解決數(shù)據(jù)存儲(chǔ)和信息傳送的方法是安裝額外的存儲(chǔ)設(shè)備和擴(kuò)展現(xiàn)有的通訊能力。這樣做是可以的,但無(wú)疑會(huì)增加組織的運(yùn)作成本。一種有效的解決數(shù)據(jù)存儲(chǔ)與信息傳輸?shù)姆椒ㄊ峭ㄟ^(guò)更有效率的代碼來(lái)存儲(chǔ)數(shù)據(jù)。這篇文章簡(jiǎn)要的介紹了數(shù)據(jù)的壓縮與解壓縮,并展示了用java.util.zip包來(lái)實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓縮是多么的方便與高效。

當(dāng)然用諸如WinZip,gzip,和Java壓縮(或jar)之類(lèi)的工具也可以實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓縮,這些工具都是獨(dú)立的應(yīng)用程序。你也可以在JAVA應(yīng)用程序中調(diào)用這些工具,但這并不是最直接的方法,也不是有效的解決方法。尤其是你想更快速地實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓縮(例如在傳輸數(shù)據(jù)到遠(yuǎn)程機(jī)器之前)。這篇文章包括以下內(nèi)容:

給出一個(gè)關(guān)于數(shù)據(jù)壓縮的簡(jiǎn)單的介紹
描述java.util.zip包
示例如何使用該包實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓縮
示例如何壓縮串行化的對(duì)象并將其存儲(chǔ)在磁碟上
示例如何通過(guò)數(shù)據(jù)壓縮來(lái)增強(qiáng)"客戶(hù)/服務(wù)"應(yīng)用程序的性能
數(shù)據(jù)壓縮概述

文件中數(shù)據(jù)冗余的最簡(jiǎn)單的類(lèi)型是"字符的復(fù)制"。讓我們先來(lái)看下面一個(gè)字符串:

JJJJJJAAAAVVVVAAAAAA
這個(gè)字符串可以用更簡(jiǎn)潔的方式來(lái)編碼,那就是通過(guò)替換每一個(gè)重復(fù)的字符串為單個(gè)的實(shí)例字符加上記錄重復(fù)次數(shù)的數(shù)字來(lái)表示,上面的字符串可以被編碼為下面的形式:

6J4A4V6A
在這里,"6J"意味著6個(gè)字符J,"4A"意味著4個(gè)字符A,以此類(lèi)推。這種字符串壓縮方式稱(chēng)為"行程長(zhǎng)度編碼"方式,簡(jiǎn)稱(chēng)RLE。

再舉一個(gè)例子,考慮一下矩形圖像的存儲(chǔ)。一個(gè)單色位圖,可以被存儲(chǔ)為下面這種形式,如圖1所示。


圖1:RLE方式下的位圖信息

另外一種方式是將圖像存為一個(gè)圖元文件:

Rectangle 11, 3, 20, 5

上面的表示方法是講矩形的起始坐標(biāo)是(11,3),寬度是20,高度是5。

上述的矩形圖像可以使用RLE編碼方式壓縮,通過(guò)對(duì)相同位記數(shù)表示如下:

0, 40
0, 40
0,10 1,20 0,10
0,10 1,1 0,18 1,1 0,10
0,10 1,1 0,18 1,1 0,10
0,10 1,1 0,18 1,1 0,10
0,10 1,20 0,10
0,40

上面第一行是講圖像的第一行由40個(gè)0組成。第三行是講圖像的第三行是由10個(gè)0加上20個(gè)1再加上10個(gè)0組成,其它行以此類(lèi)推。

大家注意,RLE方法需要將其表示的文件與編碼文件分開(kāi)。所以,這種方法不能應(yīng)用于所有的文件。其它的壓縮技術(shù)包括變長(zhǎng)編碼(也被稱(chēng)為哈夫曼編碼),還有其它的方法。要想了解更詳細(xì)的信息,請(qǐng)參考有關(guān)數(shù)據(jù)和圖像壓縮技術(shù)方面的圖書(shū),一定會(huì)有收獲的。

數(shù)據(jù)壓縮有很多益處。不管怎么說(shuō),最主要的好處就是減少存儲(chǔ)方面的需求。同樣的,對(duì)于數(shù)據(jù)通信來(lái)講,壓縮數(shù)據(jù)在媒體中的將導(dǎo)致信息傳輸數(shù)據(jù)的提升。數(shù)據(jù)的壓縮能夠通過(guò)軟件在現(xiàn)有的硬件設(shè)備上實(shí)現(xiàn)或者通過(guò)帶有壓縮技術(shù)的特殊的硬件設(shè)備來(lái)實(shí)現(xiàn)。圖表2顯示了基本的數(shù)據(jù)壓縮結(jié)構(gòu)圖。


圖2:數(shù)據(jù)壓縮結(jié)構(gòu)圖

ZIP VS GZIP

如果你是在Windows系統(tǒng)下工作,你可能會(huì)對(duì)工具WinZip很熟悉,是用來(lái)創(chuàng)建壓縮檔案和解開(kāi)壓縮檔案的。而在UNIX平臺(tái)上,會(huì)有一些不同,命令tar用來(lái)創(chuàng)建一個(gè)檔案文件(并不壓縮),其它的程序(gzip或compress)用來(lái)創(chuàng)建一個(gè)壓縮檔案。

WinZip和PkZip之類(lèi)的工具同時(shí)扮演著歸檔和壓縮兩個(gè)角色。他們將文件壓縮并將其歸檔。另一方面,gzip并不將文件歸檔。所以,在UNIX平臺(tái)上,命令tar通常用來(lái)創(chuàng)建一個(gè)檔案文件,然后命令gzip來(lái)將檔案文件壓縮。

Java.util.zip包

Java提供了java.util.zip包用來(lái)兼容ZIP格式的數(shù)據(jù)壓縮。它提供了一系列的類(lèi)用來(lái)讀取,創(chuàng)建,修改ZIP和GZIP格式的文件。它還提供了工具類(lèi)來(lái)計(jì)算任意輸入流的數(shù)目,這可以用來(lái)驗(yàn)證輸入數(shù)據(jù)的有效性。該包提供了一個(gè)接口,十四個(gè)類(lèi),和兩個(gè)異常處理類(lèi),如表1所示。

表1: java.util.zip包

條目 類(lèi)型 描述
Checksum 接口 被類(lèi)Adler32和CRC32實(shí)現(xiàn)的接口
Adler32 類(lèi) 使用Alder32算法來(lái)計(jì)算Checksum數(shù)目
CheckedInputStream 類(lèi) 一個(gè)輸入流,保存著被讀取數(shù)據(jù)的Checksum
CheckedOutputStream 類(lèi) 一個(gè)輸出流,保存著被讀取數(shù)據(jù)的Checksum
CRC32 類(lèi) 使用CRC32算法來(lái)計(jì)算Checksum數(shù)目
Deflater 類(lèi) 使用ZLIB壓縮類(lèi),支持通常的壓縮方式
DeflaterOutputStream 類(lèi) 一個(gè)輸出過(guò)濾流,用來(lái)壓縮Deflater格式數(shù)據(jù)
GZIPInputStream 類(lèi) 一個(gè)輸入過(guò)濾流,讀取GZIP格式壓縮數(shù)據(jù)
GZIPOutputStream 類(lèi) 一個(gè)輸出過(guò)濾流,讀取GZIP格式壓縮數(shù)據(jù)
Inflater 類(lèi) 使用ZLIB壓縮類(lèi),支持通常的解壓方式
InlfaterInputStream 類(lèi) 一個(gè)輸入過(guò)濾流,用來(lái)解壓Inlfater格式的壓縮數(shù)據(jù)
ZipEntry 類(lèi) 存儲(chǔ)ZIP條目
ZipFile 類(lèi) 從ZIP文件中讀取ZIP條目
ZipInputStream 類(lèi) 一個(gè)輸入過(guò)濾流,用來(lái)讀取ZIP格式文件中的文件
ZipOutputStream 類(lèi) 一個(gè)輸出過(guò)濾流,用來(lái)向ZIP格式文件口寫(xiě)入文件
DataFormatException 異常類(lèi) 拋出一個(gè)數(shù)據(jù)格式錯(cuò)誤
ZipException 異常類(lèi) 拋出一個(gè)ZIP文件



注意:ZLIB壓縮類(lèi)最初是作為可移植的網(wǎng)絡(luò)圖像文件格式(PNG)標(biāo)準(zhǔn)的一部分開(kāi)發(fā)的,是不受專(zhuān)利保護(hù)的。

從ZIP文件中解壓縮和提取數(shù)據(jù)

java.util.zip包提供了數(shù)據(jù)壓縮與解壓縮所需要的類(lèi)。ZIP文件的解壓縮實(shí)質(zhì)上就是從輸入流中讀取數(shù)據(jù)。Java.util.zip包提供了類(lèi)ZipInputStream來(lái)讀取ZIP文件。ZipInputStream流的創(chuàng)建與其它輸入流的創(chuàng)建沒(méi)什么兩樣。舉個(gè)例子,下面的代碼段創(chuàng)建了一個(gè)輸入流來(lái)讀取ZIP格式的文件:

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






ZIP輸入流打開(kāi)后,你可以使用getNextEntry方法來(lái)讀取ZIP文件中的條目數(shù),該方法返回一個(gè)ZipEntry對(duì)象。如果到達(dá)文件的尾部,getNextEntry返回null:

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






現(xiàn)在,你應(yīng)該建立一個(gè)輸出流,如下所示:

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






注意:在這段代碼中我們用BufferedOutputStream代替了ZIPOutputStream。ZIPOutputStream和GZIPOutputStream使用內(nèi)置的512字節(jié)緩沖。當(dāng)緩沖區(qū)的大小大于512字節(jié)時(shí),使用BufferedOutputStream才是正確的(例子中設(shè)置為2048)。ZIPOutputStream不允許你設(shè)置緩沖區(qū)的大小,GZIPOutputStream也是一樣,但創(chuàng)建 GZIPOutputStream 對(duì)象時(shí)可以通過(guò)構(gòu)造函數(shù)的參數(shù)指定內(nèi)置的緩沖尺寸。

這段代碼中,使用ZIP內(nèi)含的條目名稱(chēng)創(chuàng)建一個(gè)文件輸出流??梢允褂胑ntry.getName來(lái)得到它的返回句柄。接著讀出被壓縮的源數(shù)據(jù),然后寫(xiě)入輸出流:

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






最后,不要忘記關(guān)閉輸入和輸出流:

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






例程1的源程序UnZip.java顯示如何解壓縮并從ZIP檔案中將文件釋放出來(lái)。測(cè)試這個(gè)例子,編譯這個(gè)類(lèi),并運(yùn)行它,傳給它一個(gè)ZIP格式的文件作為參數(shù):

prompt> java UnZip somefile.zip

注意:somefile.zip應(yīng)該是一個(gè)ZIP壓縮檔案,可以用任何一種ZIP壓縮工具來(lái)創(chuàng)建,例如WinZip。

例程1源代碼:

UnZip.java
import java.io.*;
import java.util.zip.*;

public class UnZip {
static 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();
}
}
}






有一點(diǎn)值得大家注意,類(lèi)ZipInputStream讀出ZIP文件序列(簡(jiǎn)單地說(shuō)就是讀出這個(gè)ZIP文件壓縮了多少文件),而類(lèi)ZipFile使用內(nèi)嵌的隨機(jī)文件訪(fǎng)問(wèn)機(jī)制讀出其中的文件內(nèi)容,所以不必順序的讀出ZIP壓縮文件序列。

注意:ZIPInputStream和ZipFile之間另外一個(gè)基本的不同點(diǎn)在于高速緩沖的使用方面。當(dāng)文件使用ZipInputStream和FileInputStream流讀出的時(shí)候,ZIP條目不使用高速緩沖。然而,如果使用ZipFile(文件名)來(lái)打開(kāi)文件,它將使用內(nèi)嵌的高速緩沖,所以如果ZipFile(文件名)被重復(fù)調(diào)用的話(huà),文件只被打開(kāi)一次。緩沖值在第二次打開(kāi)進(jìn)使用。如果你工作在UNIX系統(tǒng)下,這是什么作用都沒(méi)有的,因?yàn)槭褂肸ipFile打開(kāi)的所有ZIP文件都在內(nèi)存中存在映射,所以使用ZipFile的性能優(yōu)于ZipInputStream。然而,如果同一ZIP文件的內(nèi)容在程序執(zhí)行期間經(jīng)常改變,或是重載的話(huà),使用ZipInputStream就成為你的首選了。

下面顯示了使用類(lèi)ZipFile來(lái)解壓一個(gè)ZIP文件的過(guò)程:

通過(guò)指定一個(gè)被讀取的ZIP文件,或者是文件名,或者是一個(gè)文件對(duì)象來(lái)創(chuàng)建一個(gè)ZipFile對(duì)象:
ZipFile zipfile = new ZipFile("figs.zip");

使用entries方法,返回一個(gè)枚舉對(duì)象,循環(huán)獲得文件的ZIP條目對(duì)象:
while(e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
// read contents and save them
}

ZIP條目作為參數(shù)傳遞給getInputStream方法,可以讀取ZIP文件中指定條目的內(nèi)容,能過(guò)其返回的輸入流(InputStram)對(duì)象可以方便的讀出ZIP條目的內(nèi)容:
is = new BufferedInputStream(zipfile.getInputStream(entry));

獲取ZIP條目的文件名,創(chuàng)建輸出流,并保存:
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);
}

最后關(guān)閉所有的輸入輸出流 dest.flush();
dest.close();
is.close();

完整的程序代碼如例程2所示。再次編譯這個(gè)文件,并傳遞一個(gè)ZIP格式的文件做為參數(shù):

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();
}
}
}






將數(shù)據(jù)壓縮歸檔入一ZIP文件

類(lèi)ZipOutputStream能夠用來(lái)將數(shù)據(jù)壓縮成一個(gè)ZIP文件。ZipOutputStream將數(shù)據(jù)寫(xiě)入ZIP格式的輸出流。下面的步驟與創(chuàng)建一個(gè)ZIP文件相關(guān)。

1、第一步是創(chuàng)建一個(gè)ZipOutputStream對(duì)象,我們將要寫(xiě)入輸出流的文件作為參數(shù)傳給它。下面的代碼演示了如何創(chuàng)建一個(gè)名為"myfigs.zip"的ZIP文件。
FileOutputStream dest = new
FileOutputStream("myfigs.zip");
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));

2、一但目標(biāo)輸出流創(chuàng)建后,下一步就是打開(kāi)數(shù)據(jù)源文件。在這個(gè)例子中,源數(shù)據(jù)文件是指那些當(dāng)前目錄下的文件。命令list用來(lái)得到當(dāng)前目錄下文件列表:

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
}






注意:這個(gè)例程能夠壓縮當(dāng)前目錄下的所有文件。它不能處理子目錄。作為一個(gè)練習(xí),你可以修改例程3來(lái)處理子目錄。

3、 為讀出的數(shù)據(jù)創(chuàng)建一個(gè)ZIP條目列表:
ZipEntry entry = new ZipEntry(files[i]))

4、 在你將數(shù)據(jù)寫(xiě)入ZIP輸出流之前,你必須使用putNextEntry方法將ZIP條目列表寫(xiě)入輸出流:
out.putNextEntry(entry);

5、 將數(shù)據(jù)寫(xiě)入ZIP文件:
int count;
while((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}

6、 最后關(guān)閉所有的輸入輸出流:
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:zipmyfigs.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();
}
}
}






注意: 條目列表可以以?xún)煞N方式加入ZIP文件中,一種是壓縮方式(DEFLATED),另一種是不壓縮方式(STORED),系統(tǒng)默認(rèn)的存儲(chǔ)方式為壓縮方式(DEFLATED)。SetMethod方法可以用來(lái)設(shè)置它的存儲(chǔ)方式。例如,設(shè)置存儲(chǔ)方式為DEFLATED(壓縮)應(yīng)該這樣做: out.setMethod(ZipOutputStream.DEFLATED) 設(shè)置存儲(chǔ)方式為(不壓縮)應(yīng)該這樣做: out.setMethod(ZipOutputStream.STORED)。

ZIP文件屬性

類(lèi)ZipEntry描述了存儲(chǔ)在ZIP文件中的壓縮文件。類(lèi)中包含有多種方法可以用來(lái)設(shè)置和獲得ZIP條目的信息。類(lèi)ZipEntry是被ZipFile和ZipInputStream使用來(lái)讀取ZIP文件,ZipOutputStream來(lái)寫(xiě)入ZIP文件的。ZipEntry中最有用的一些方法顯示在下面的表格2中,并且有相應(yīng)的描述。
表格 2: 類(lèi)ZipEntry中一些有用的方法

方法簽名 描述
public String getComment() 返回條目的注釋, 沒(méi)有返回null
public long getCompressedSize() 返回條目壓縮后的大小, 未知返回-1
public int getMethod() 返回條目的壓縮方式,沒(méi)有指定返回 -1
public String getName() 返回條目的名稱(chēng)
public long getSize() 返回未被壓縮的條目的大小,未知返回-1
public long getTime() 返回條目的修改時(shí)間, 沒(méi)有指定返回-1
public void setComment(String c) 設(shè)置條目的注釋
public void setMethod(int method) 設(shè)置條目的壓縮方式
public void setSize(long size) 設(shè)置沒(méi)有壓縮的條目的大小
public void setTime(long time) 設(shè)置條目的修改時(shí)間



求和校驗(yàn)

java.util.zip包中另外一些比較重要的類(lèi)是Adler32和CRC32,它們實(shí)現(xiàn)了java.util.zip.Checksum接口,并估算了壓縮數(shù)據(jù)的校驗(yàn)和(checksum)。眾所周知,在運(yùn)算速度方面,Adler32算法比CRC32算法要有一定的優(yōu)勢(shì);但在數(shù)據(jù)可信度方面,CRC32算法則要更勝一籌。正所謂,"魚(yú)與熊掌,不可兼得。",大家只好在不同的場(chǎng)合下,加以取舍了。GetValue方法可以用來(lái)獲得當(dāng)前的checksum值,reset方法能夠重新設(shè)置checksum為其缺省的值。

求和校驗(yàn)一般用來(lái)校驗(yàn)文件和信息是否正確的傳送。舉個(gè)例子,假設(shè)你想創(chuàng)建一個(gè)ZIP文件,然后將其傳送到遠(yuǎn)程計(jì)算機(jī)上。當(dāng)?shù)竭_(dá)遠(yuǎn)程計(jì)算機(jī)后,你就可以使用checksum檢驗(yàn)在傳輸過(guò)程中文件是否發(fā)生錯(cuò)誤。為了演示如何創(chuàng)建checksums,我們修改了例程1和例程3,在例程4和例程5中使用了兩個(gè)新類(lèi),一個(gè)是CheckedInputStream,另一個(gè)是CheckedOutputStream。(大家注意:這兩段代碼在壓縮與解壓縮過(guò)程中,使用了同一種算法,求數(shù)據(jù)的checksum值。)

例程4源代碼:

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:zipmyfigs.zip");
CheckedOutputStream checksum = new
CheckedOutputStream(dest, new Adler32());
ZipOutputStream out = new
ZipOutputStream(new
BufferedOutputStream(checksum));
//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();
System.out.println("checksum:
"+checksum.getChecksum().getValue());
} catch(Exception e) {
e.printStackTrace();
}
}
}






例程5源代碼:

UnZip.java
import java.io.*;
import java.util.zip.*;

public class UnZip {
public static void main (String argv[]) {
try {
final int BUFFER = 2048;
BufferedOutputStream dest = null;
FileInputStream fis = new
FileInputStream(argv[0]);
CheckedInputStream checksum = new
CheckedInputStream(fis, new Adler32());
ZipInputStream zis = new
ZipInputStream(new
BufferedInputStream(checksum));
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();
System.out.println("Checksum:
"+checksum.getChecksum().getValue());
} catch(Exception e) {
e.printStackTrace();
}
}
}






測(cè)試?yán)?和5,編譯類(lèi)文件并運(yùn)行類(lèi)Zip來(lái)創(chuàng)建一個(gè)壓縮檔案(程序會(huì)計(jì)算出checksum值并顯示在屏幕上),然后運(yùn)行UnZip類(lèi)來(lái)解壓縮這個(gè)檔案(屏幕上同樣會(huì)打印出一個(gè)checksum值)。兩個(gè)值必須完全相同,否則說(shuō)明出錯(cuò)了。Checksums在數(shù)據(jù)校驗(yàn)方面非常有用。例如,你可以創(chuàng)建一個(gè)ZIP文件,然后連同checksum值一同傳遞給你的朋友。你的朋友解壓縮文件后,將生成的checksum值與你提供的作一比較,如果相同則說(shuō)明在傳遞過(guò)程中沒(méi)有發(fā)生錯(cuò)誤。

壓縮對(duì)象

我們已經(jīng)看到如何將文件中的數(shù)據(jù)壓縮并將其歸檔。但如果你想壓縮的數(shù)據(jù)不在文件中時(shí),應(yīng)該怎么辦呢?假設(shè)有這樣一個(gè)例子,你通過(guò)套接字(socket)來(lái)傳遞一個(gè)大對(duì)象。為了提高應(yīng)用程序的性能,你可能在通過(guò)網(wǎng)絡(luò)開(kāi)始傳遞前將數(shù)據(jù)壓縮,然后在目的地將其解壓縮。另外一個(gè)例子,我們假設(shè)你想將一個(gè)對(duì)象用壓縮格式存儲(chǔ)在磁碟上,ZIP格式是基于記錄方式的,不適合這項(xiàng)工作。GZIP更適合用來(lái)實(shí)現(xiàn)這種對(duì)單一數(shù)據(jù)流的操作?,F(xiàn)在,我們來(lái)示例一下,如果在寫(xiě)入磁碟前將數(shù)據(jù)壓縮,并在讀出時(shí)將數(shù)據(jù)解壓縮。示例程序6是一個(gè)在單一JVM(java虛擬機(jī))實(shí)現(xiàn)了Serializable接口的簡(jiǎn)單類(lèi),我們想要串行化該類(lèi)的實(shí)例。

例程6源代碼:

Employee.java
import java.io.*;

public class Employee implements Serializable {
String name;
int age;
int salary;

public Employee(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}

public void print() {
System.out.println("Record for: "+name);
System.out.println("Name: "+name);
System.out.println("Age: "+age);
System.out.println("Salary: "+salary);
}
}






現(xiàn)在,寫(xiě)另外一個(gè)類(lèi)來(lái)創(chuàng)建兩個(gè)從Employee類(lèi)實(shí)例化而來(lái)的對(duì)象。示例程序7從Employee類(lèi)創(chuàng)建了兩個(gè)對(duì)象(sarah和sam)。然后將它們的狀態(tài)以壓縮的格式存儲(chǔ)在一個(gè)文件中。

示例程序7源代碼:

SaveEmployee.java
import java.io.*;
import java.util.zip.*;

public class SaveEmployee {
public static void main(String argv[]) throws
Exception {
// create some objects
Employee sarah = new Employee("S. Jordan", 28,
56000);
Employee sam = new Employee("S. McDonald", 29,
58000);
// serialize the objects sarah and sam
FileOutputStream fos = new
FileOutputStream("db");
GZIPOutputStream gz = new GZIPOutputStream(fos);
ObjectOutputStream oos = new
ObjectOutputStream(gz);
oos.writeObject(sarah);
oos.writeObject(sam);
oos.flush();
oos.close();
fos.close();
}
}






現(xiàn)在,示例程序8中的ReadEmpolyee類(lèi)是用來(lái)重新構(gòu)建兩個(gè)對(duì)象的狀態(tài)。一但構(gòu)建成功,就調(diào)用print方法將其打印出來(lái)。

示例程序8源代碼:

ReadEmployee.java
import java.io.*;
import java.util.zip.*;

public class ReadEmployee {
public static void main(String argv[]) throws
Exception{
//deserialize objects sarah and sam
FileInputStream fis = new FileInputStream("db");
GZIPInputStream gs = new GZIPInputStream(fis);
ObjectInputStream ois = new ObjectInputStream(gs);
Employee sarah = (Employee) ois.readObject();
Employee sam = (Employee) ois.readObject();
//print the records after reconstruction of state
sarah.print();
sam.print();
ois.close();
fis.close();
}
}






同樣的思想可以用于在網(wǎng)絡(luò)間通過(guò)(socket)傳輸?shù)拇髮?duì)象。下面的代碼段示例了如何在客戶(hù)/服務(wù)器之間實(shí)現(xiàn)大對(duì)象的壓縮:

// write to client
GZIPOutputStream gzipout = new
GZIPOutputStream(socket.getOutputStream());
ObjectOutputStream oos = new
ObjectOutputStream(gzipout);
oos.writeObject(obj);
gzipos.finish();






下面的代碼段顯示了客戶(hù)端從服務(wù)器端接收到數(shù)據(jù)后,如何將其解壓:

// read from server
Socket socket = new Socket(remoteServerIP, PORT);
GZIPInputStream gzipin = new
GZIPInputStream(socket.getInputStream());
ObjectInputStream ois = new ObjectInputStream(gzipin);
Object o = ois.readObject();






如何對(duì)JAR文件進(jìn)行操作呢?

Java檔案文件(JAR)格式是基于標(biāo)準(zhǔn)的ZIP文件格式,并附有可選擇的文件清單列表。如果你想要在你我的應(yīng)用程序中創(chuàng)建JAR文件或從JAR文件中解壓縮文件,可以使用java.util.jar包,它提供了讀寫(xiě)JAR文件的類(lèi)。使用java.util.jar包提供的類(lèi)與本文所講述的java.util.zip包十分相似。所以你應(yīng)該能夠重新編寫(xiě)本文的源代碼,如果你想使用java.util.jar包的話(huà)。

結(jié)束語(yǔ)

本文討論了你可以在應(yīng)用程序中使用的數(shù)據(jù)壓縮與解壓的應(yīng)用程序接口,本文的示例程序演示了如何使用java.util.zip包來(lái)壓縮數(shù)據(jù)與解壓縮數(shù)據(jù)。現(xiàn)在你可以利用這個(gè)工具在你的應(yīng)用程序中實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓了。

本文也說(shuō)明了如何在絡(luò)傳輸中實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓縮,以減少網(wǎng)絡(luò)阻塞和增強(qiáng)你的客戶(hù)/服務(wù)器模式應(yīng)用程序的性能。在網(wǎng)絡(luò)傳輸中實(shí)現(xiàn)數(shù)據(jù)的壓縮,只有當(dāng)傳輸?shù)臄?shù)據(jù)量達(dá)到成百上千字節(jié)時(shí),你才會(huì)感覺(jué)到程序性能的提升,如果僅僅是傳遞一個(gè)字符串對(duì)象,對(duì)應(yīng)用程序是沒(méi)什么影響的。

更多的資料信息:
? The java.util.zip Package
? The java.util.jar Package
? Object Serialization
? Transporting Objects over Sockets
本文所演示的代碼經(jīng)本人在Win2000平臺(tái)下使用Java2SDK1.4.0調(diào)試通過(guò),可以在這里下載。
代碼1、代碼2、代碼3、代碼4、代碼5、代碼6、代碼7、代碼8
[@more@]

網(wǎng)頁(yè)題目:利用JAVAAPI函數(shù)實(shí)現(xiàn)數(shù)據(jù)的壓縮與解壓縮(轉(zhuǎn))
網(wǎng)站地址:http://chinadenli.net/article12/ieghgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、做網(wǎng)站、面包屑導(dǎo)航、微信小程序、云服務(wù)器品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司
九九热最新视频免费观看| 91欧美一区二区三区成人| 亚洲精品偷拍视频免费观看| 免费特黄一级一区二区三区| 高中女厕偷拍一区二区三区| 爱在午夜降临前在线观看| 亚洲人午夜精品射精日韩| 国产乱人伦精品一区二区三区四区| 少妇熟女亚洲色图av天堂| 亚洲国产精品久久网午夜| 在线亚洲成人中文字幕高清| 又黄又爽禁片视频在线观看 | 欧美日韩国产二三四区| 国产级别精品一区二区视频| 亚洲欧美日韩在线中文字幕| 国产午夜精品亚洲精品国产| 免费在线播放不卡视频| 国产精品午夜视频免费观看 | 亚洲一区二区欧美在线| 在线观看日韩欧美综合黄片| 亚洲熟女乱色一区二区三区| 久久精品一区二区少妇| 国产在线观看不卡一区二区| 日本久久中文字幕免费| 午夜国产精品福利在线观看| 精品香蕉一区二区在线| 国产精品亚洲一级av第二区| 日韩一区二区三区18| 高清在线精品一区二区| 亚洲永久一区二区三区在线| 国产又大又黄又粗又免费| 日韩三极片在线免费播放| 欧美不卡高清一区二区三区| 小黄片大全欧美一区二区| 日韩精品中文在线观看| 午夜福利黄片免费观看| 黄色国产一区二区三区| 大香蕉久草网一区二区三区| 日韩综合国产欧美一区| 日本中文字幕在线精品| 精品精品国产欧美在线|