利用JAVA API函數實現數據的壓縮與解壓縮


 

綜述

許多信息資料都或多或少的包含一些多余的數據。通常會導致在客戶端與服務器之間,應用程序與計算機之間極大的數據傳輸量。最常見的解決數據存儲和信息傳送的方法是安裝額外的存儲設備和擴展現有的通訊能力。這樣做是可以的,但無疑會增加組織的運作成本。一種有效的解決數據存儲與信息傳輸的方法是通過更有效率的代碼來存儲數據。這篇文章簡要的介紹了數據的壓縮與解壓縮,並展示了用java.util.zip包來實現數據的壓縮與解壓縮是多么的方便與高效。

當然用諸如WinZip,gzip,和Java壓縮(或jar)之類的工具也可以實現數據的壓縮與解壓縮,這些工具都是獨立的應用程序。你也可以在JAVA應用程序中調用這些工具,但這並不是最直接的方法,也不是有效的解決方法。尤其是你想更快速地實現數據的壓縮與解壓縮(例如在傳輸數據到遠程機器之前)。這篇文章包括以下內容:

  • 給出一個關於數據壓縮的簡單的介紹
  • 描述java.util.zip包
  • 示例如何使用該包實現數據的壓縮與解壓縮
  • 示例如何壓縮串行化的對象並將其存儲在磁碟上
  • 示例如何通過數據壓縮來增強"客戶/服務"應用程序的性能
 

數據壓縮概述

文件中數據冗余的最簡單的類型是"字符的復制"。讓我們先來看下面一個字符串:

  • JJJJJJAAAAVVVVAAAAAA 這個字符串可以用更簡潔的方式來編碼,那就是通過替換每一個重復的字符串為單個的實例字符加上記錄重復次數的數字來表示,上面的字符串可以被編碼為下面的形式:

  • 6J4A4V6A 在這里,"6J"意味着6個字符J,"4A"意味着4個字符A,以此類推。這種字符串壓縮方式稱為"行程長度編碼"方式,簡稱RLE。

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

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

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

Rectangle 11, 3, 20, 5

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

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

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個0組成。第三行是講圖像的第三行是由10個0加上20個1再加上10個0組成,其它行以此類推。

大家注意,RLE方法需要將其表示的文件與編碼文件分開。所以,這種方法不能應用於所有的文件。其它的壓縮技術包括變長編碼(也被稱為哈夫曼編碼),還有其它的方法。要想了解更詳細的信息,請參考有關數據和圖像壓縮技術方面的圖書,一定會有收獲的。

數據壓縮有很多益處。不管怎么說,最主要的好處就是減少存儲方面的需求。同樣的,對於數據通信來講,壓縮數據在媒體中的將導致信息傳輸數據的提升。數據的壓縮能夠通過軟件在現有的硬件設備上實現或者通過帶有壓縮技術的特殊的硬件設備來實現。圖表2顯示了基本的數據壓縮結構圖。

圖 2. 數據壓縮結構圖
圖 2.數據壓縮結構圖

ZIP VS GZIP

如果你是在Windows系統下工作,你可能會對工具WinZip很熟悉,是用來創建壓縮檔案和解開壓縮檔案的。而在UNIX平台上,會有一些不同,命令tar用來創建一個檔案文件(並不壓縮),其它的程序(gzip或compress)用來創建一個壓縮檔案。

WinZip和PkZip之類的工具同時扮演着歸檔和壓縮兩個角色。他們將文件壓縮並將其歸檔。另一方面,gzip並不將文件歸檔。所以,在UNIX平台上,命令tar通常用來創建一個檔案文件,然后命令gzip來將檔案文件壓縮。

Java.util.zip 包

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

表 1. java.util.zip 包
條目 類型 描述
Checksum 接口 被類Adler32和CRC32實現的接口
Adler32 使用Alder32算法來計算Checksum數目
CheckedInputStream 一個輸入流,保存着被讀取數據的Checksum
CheckedOutputStream 一個輸出流,保存着被讀取數據的Checksum
CRC32 使用CRC32算法來計算Checksum數目
Deflater 使用ZLIB壓縮類,支持通常的壓縮方式
DeflaterOutputStream 一個輸出過濾流,用來壓縮Deflater格式數據
GZIPInputStream 一個輸入過濾流,讀取GZIP格式壓縮數據
GZIPOutputStream 一個輸出過濾流,讀取GZIP格式壓縮數據
Inflater 使用ZLIB壓縮類,支持通常的解壓方式
InlfaterInputStream 一個輸入過濾流,用來解壓Inlfater格式的壓縮數據
ZipEntry 存儲ZIP條目
ZipFile 從ZIP文件中讀取ZIP條目
ZipInputStream 一個輸入過濾流,用來讀取ZIP格式文件中的文件
ZipOutputStream 一個輸出過濾流,用來向ZIP格式文件口寫入文件
DataFormatException 異常類 拋出一個數據格式錯誤
ZipException 異常類 拋出一個ZIP文件

注意:ZLIB壓縮類最初是作為可移植的網絡圖像文件格式(PNG)標准的一部分開發的,是不受專利保護的。

 

從ZIP文件中解壓縮和提取數據

java.util.zip包提供了數據壓縮與解壓縮所需要的類。ZIP文件的解壓縮實質上就是從輸入流中讀取數據。Java.util.zip包提供了類ZipInputStream來讀取ZIP文件。ZipInputStream流的創建與其它輸入流的創建沒什么兩樣。舉個例子,下面的代碼段創建了一個輸入流來讀取ZIP格式的文件:

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

ZIP輸入流打開后,你可以使用getNextEntry方法來讀取ZIP文件中的條目數,該方法返回一個ZipEntry對象。如果到達文件的尾部,getNextEntry返回null:

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代替了ZIPOutputStream。ZIPOutputStream和GZIPOutputStream使用內置的512字節緩沖。當緩沖區的大小大於512字節時,使用BufferedOutputStream才是正確的(例子中設置為2048)。ZIPOutputStream不允許你設置緩沖區的大小,GZIPOutputStream也是一樣,但創建 GZIPOutputStream 對象時可以通過構造函數的參數指定內置的緩沖尺寸。

這段代碼中,使用ZIP內含的條目名稱創建一個文件輸出流。可以使用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的源程序UnZip.java顯示如何解壓縮並從ZIP檔案中將文件釋放出來。測試這個例子,編譯這個類,並運行它,傳給它一個ZIP格式的文件作為參數:

prompt> java UnZip somefile.zip

注意:somefile.zip應該是一個ZIP壓縮檔案,可以用任何一種ZIP壓縮工具來創建,例如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();
      }
   }
}

有一點值得大家注意,類ZipInputStream讀出ZIP文件序列(簡單地說就是讀出這個ZIP文件壓縮了多少文件),而類ZipFile使用內嵌的隨機文件訪問機制讀出其中的文件內容,所以不必順序的讀出ZIP壓縮文件序列。

注意:ZIPInputStream和ZipFile之間另外一個基本的不同點在於高速緩沖的使用方面。當文件使用ZipInputStream和FileInputStream流讀出的時候,ZIP條目不使用高速緩沖。然而,如果使用ZipFile(文件名)來打開文件,它將使用內嵌的高速緩沖,所以如果ZipFile(文件名)被重復調用的話,文件只被打開一次。緩沖值在第二次打開進使用。如果你工作在UNIX系統下,這是什么作用都沒有的,因為使用ZipFile打開的所有ZIP文件都在內存中存在映射,所以使用ZipFile的性能優於ZipInputStream。然而,如果同一ZIP文件的內容在程序執行期間經常改變,或是重載的話,使用ZipInputStream就成為你的首選了。

下面顯示了使用類ZipFile來解壓一個ZIP文件的過程:

  1. 通過指定一個被讀取的ZIP文件,或者是文件名,或者是一個文件對象來創建一個ZipFile對象: ZipFile zipfile = new ZipFile("figs.zip");

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

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

  4. 獲取ZIP條目的文件名,創建輸出流,並保存: 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、 一但目標輸出流創建后,下一步就是打開數據源文件。在這個例子中,源數據文件是指那些當前目錄下的文件。命令list用來得到當前目錄下文件列表:

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、 為讀出的數據創建一個ZIP條目列表:
ZipEntry entry = new ZipEntry(files[i]))

4、 在你將數據寫入ZIP輸出流之前,你必須使用putNextEntry方法將ZIP條目列表寫入輸出流:
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();
      }
   }
}

注意: 條目列表可以以兩種方式加入ZIP文件中,一種是壓縮方式(DEFLATED),另一種是不壓縮方式(STORED),系統默認的存儲方式為壓縮方式(DEFLATED)。SetMethod方法可以用來設置它的存儲方式。 例如,設置存儲方式為DEFLATED(壓縮)應該這樣做: out.setMethod(ZipOutputStream.DEFLATED) 設置存儲方式為(不壓縮)應該這樣做: out.setMethod(ZipOutputStream.STORED)。

 

ZIP文件屬性

類ZipEntry描述了存儲在ZIP文件中的壓縮文件。類中包含有多種方法可以用來設置和獲得ZIP條目的信息。類ZipEntry是被ZipFile和ZipInputStream使用來讀取ZIP文件,ZipOutputStream來寫入ZIP文件的。ZipEntry中最有用的一些方法顯示在下面的表格2中,並且有相應的描述。

表格 2. 類 ZipEntry 中一些有用的方法
方法簽名 描述
public String getComment() 返回條目的注釋, 沒有返回null
public long getCompressedSize() 返回條目壓縮后的大小, 未知返回-1
public int getMethod() 返回條目的壓縮方式,沒有指定返回 -1
public String getName() 返回條目的名稱
public long getSize() 返回未被壓縮的條目的大小,未知返回-1
public long getTime() 返回條目的修改時間, 沒有指定返回-1
public void setComment(String c) 設置條目的注釋
public void setMethod(int method) 設置條目的壓縮方式
public void setSize(long size) 設置沒有壓縮的條目的大小
public void setTime(long time) 設置條目的修改時間
 

求和校驗

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

求和校驗一般用來校驗文件和信息是否正確的傳送。舉個例子,假設你想創建一個ZIP文件,然后將其傳送到遠程計算機上。當到達遠程計算機后,你就可以使用checksum檢驗在傳輸過程中文件是否發生錯誤。為了演示如何創建checksums,我們修改了清單 1 和清單 3,在清單 4和清單 5中使用了兩個新類,一個是CheckedInputStream,另一個是CheckedOutputStream。(大家注意:這兩段代碼在壓縮與解壓縮過程中,使用了同一種算法,求數據的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:\\zip\\myfigs.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();
      }
   }
}

測試清單 4 和 5,編譯類文件並運行類Zip來創建一個壓縮檔案(程序會計算出checksum值並顯示在屏幕上),然后運行UnZip類來解壓縮這個檔案(屏幕上同樣會打印出一個checksum值)。兩個值必須完全相同,否則說明出錯了。Checksums在數據校驗方面非常有用。例如,你可以創建一個ZIP文件,然后連同checksum值一同傳遞給你的朋友。你的朋友解壓縮文件后,將生成的checksum值與你提供的作一比較,如果相同則說明在傳遞過程中沒有發生錯誤。

 

壓縮對象

我們已經看到如何將文件中的數據壓縮並將其歸檔。但如果你想壓縮的數據不在文件中時,應該怎么辦呢?假設有這樣一個例子,你通過套接字(socket)來傳遞一個大對象。為了提高應用程序的性能,你可能在通過網絡開始傳遞前將數據壓縮,然后在目的地將其解壓縮。另外一個例子, 我們假設你想將一個對象用壓縮格式存儲在磁碟上,ZIP格式是基於記錄方式的,不適合這項工作。GZIP更適合用來實現這種對單一數據流的操作。 現在,我們來示例一下,如果在寫入磁碟前將數據壓縮,並在讀出時將數據解壓縮。示清單 序6是一個在單一JVM(java虛擬機)實現了Serializable接口的簡單類,我們想要串行化該類的實例。

清單 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);
  }
}

現在,寫另外一個類來創建兩個從Employee類實例化而來的對象。清單 7 從Employee類創建了兩個對象(sarah和sam)。然后將它們的狀態以壓縮的格式存儲在一個文件中。

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

現在,清單 8 中的 ReadEmpolyee 類是用來重新構建兩個對象的狀態。一但構建成功,就調用print方法將其打印出來。

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

同樣的思想可以用於在網絡間通過(socket)傳輸的大對象。下面的代碼段示例了如何在客戶/服務器之間實現大對象的壓縮:

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

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

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

如何對JAR文件進行操作呢?

Java檔案文件(JAR)格式是基於標准的ZIP文件格式,並附有可選擇的文件清單列表。如果你想要在你我的應用程序中創建JAR文件或從JAR文件中解壓縮文件,可以使用java.util.jar包,它提供了讀寫JAR文件的類。使用java.util.jar包提供的類與本文所講述的java.util.zip包十分相似。所以你應該能夠重新編寫本文的源代碼,如果你想使用java.util.jar包的話。

 

結束語

本文討論了你可以在應用程序中使用的數據壓縮與解壓的應用程序接口,本文的示例程序演示了如何使用java.util.zip包來壓縮數據與解壓縮數據。現在你可以利用這個工具在你的應用程序中實現數據的壓縮與解壓了。

本文也說明了如何在絡傳輸中實現數據的壓縮與解壓縮,以減少網絡阻塞和增強你的客戶/服務器模式應用程序的性能。在網絡傳輸中實現數據的壓縮,只有當傳輸的數據量達到成百上千字節時,你才會感覺到程序性能的提升,如果僅僅是傳遞一個字符串對象,對應用程序是沒什么影響的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM