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

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

轉轉:
http://www.cnblogs.com/zhang-qiang/articles/2051499.html
發佈了5 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章