2010-01-14 25 views
23

Tôi đang cố gắng viết một hàm sẽ chấp nhận InputStream với dữ liệu tệp được nén và sẽ trả lại một số InputStream khác với dữ liệu đã giải nén.Giải nén tệp từ InputStream và trả lại một InputStream khác

Các tập tin nén sẽ chỉ chứa một tập tin duy nhất và do đó không có yêu cầu của việc tạo ra các thư mục, vv ...

Tôi cố gắng nhìn vào ZipInputStream và những người khác nhưng tôi bối rối bởi rất nhiều loại khác nhau của con suối trong Java.

+1

gì đã bạn đã thử? Vui lòng thêm một số ví dụ về mã. –

Trả lời

40

Các khái niệm

GZipinputstream là dành cho dòng (hoặc file) ziped như gzip ("gz" mở rộng). Nó không có bất kỳ thông tin tiêu đề nào.

GZipInputStream is for [zippeddata] 

Nếu bạn có tệp zip thực, bạn phải sử dụng tệp ZipFile để mở tệp, yêu cầu danh sách tệp (một ví dụ) và yêu cầu luồng nhập giải nén.

ZipFile is for a file with [header information + zippeddata] 

phương pháp của bạn, nếu bạn có các tập tin, sẽ là một cái gì đó như:

// ITS PSEUDOCODE!! 

private InputStream extractOnlyFile(String path) { 
    ZipFile zf = new ZipFile(path); 
    Enumeration e = zf.entries(); 
    ZipEntry entry = (ZipEntry) e.nextElement(); // your only file 
    return zf.getInputStream(entry); 
} 

Đọc một InputStream với nội dung của một tập tin .zip

Ok, nếu bạn có một InputStream bạn có thể sử dụng (như @cletus nói) ZipInputStream. Nó đọc một luồng bao gồm dữ liệu tiêu đề.

ZipInputStream is for a stream with [header information + zippeddata] 

Quan trọng: nếu bạn có các tập tin trong máy tính của bạn, bạn có thể sử dụng ZipFile lớp để truy cập nó một cách ngẫu nhiên

Đây là một mẫu của việc đọc một zip-file thông qua một InputStream:

import java.io.FileInputStream; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipInputStream; 


public class Main { 
    public static void main(String[] args) throws Exception 
    { 
     FileInputStream fis = new FileInputStream("c:/inas400.zip"); 

     // this is where you start, with an InputStream containing the bytes from the zip file 
     ZipInputStream zis = new ZipInputStream(fis); 
     ZipEntry entry; 
      // while there are entries I process them 
     while ((entry = zis.getNextEntry()) != null) 
     { 
      System.out.println("entry: " + entry.getName() + ", " + entry.getSize()); 
        // consume all the data from this entry 
      while (zis.available() > 0) 
       zis.read(); 
        // I could close the entry, but getNextEntry does it automatically 
        // zis.closeEntry() 
     } 
    } 
} 
+0

Tôi đã sửa mã, ZipInputStream phải bọc luồng đầu vào gốc :). Thanx! – helios

+0

Helios: zipinput.getNextEntry() sẽ trả về đối tượng ZipEntry. Làm thế nào để chuyển đổi nó thành một dòng? –

+0

zipinputstream đại diện cho một luồng đầu vào của dữ liệu đã giải nén của tệp. Đó là lý do tại sao tôi trở lại "zipinput". Nhưng nó phải đọc các tiêu đề và vị trí ở đầu dữ liệu nén hiện tại để bắt đầu. Đó là lý do tại sao tôi lần đầu tiên gọi "getnextentry". Để làm cho zipinputstream đọc tiêu đề đó và chuẩn bị giải nén mục nhập của nó (và tất nhiên, để biết tên tệp đã nén). – helios

2

Trừ khi tôi bỏ lỡ điều gì đó, bạn hoàn toàn nên thử và nhận ZipInputStream để làm việc và không có lý do gì nên không (tôi đã chắc chắn sử dụng nó trong một số trường hợp).

Những gì bạn cần làm là thử và nhận ZipInputStream để hoạt động và nếu bạn không thể, hãy đăng mã và chúng tôi sẽ giúp bạn với bất kỳ vấn đề nào bạn gặp phải.

Dù bạn làm gì, đừng cố gắng và phát minh lại chức năng của nó.

+2

anh ta dường như đã thử điều đó và không hiểu cách sử dụng nó. – Bozho

+7

Để công bằng, 'java.util.zip' là một API khá khó chịu – skaffman

6

Nếu bạn có thể thay đổi dữ liệu đầu vào, tôi khuyên bạn nên sử dụng GZIPInputStream.

GZipInputStream khác với ZipInputStream vì bạn chỉ có một dữ liệu bên trong. Vì vậy, toàn bộ luồng đầu vào đại diện cho toàn bộ tệp. Trong ZipInputStream toàn bộ luồng cũng chứa cấu trúc của (các) tệp bên trong nó, có thể là nhiều.

+1

Tệp không nằm trong tầm kiểm soát của tôi. Đó là một tập tin mà tôi tải về từ một máy chủ. Tôi sử dụng để lưu nó vào đĩa và sau đó giải nén nó, nhưng bây giờ tôi đang suy nghĩ về giải nén nó trong bộ nhớ. –

+0

Vấn đề gì không thực sự nếu các byte bắt nguồn từ một ổ cắm mạng hoặc từ một tệp. Sự khác biệt được tạo ra giữa kho lưu trữ zip và một khối dữ liệu nén. Nếu bạn đã viết và đọc dữ liệu, có lẽ bạn sẽ không thực sự quan tâm đến kho lưu trữ với siêu dữ liệu của nó, và sau đó GZipStream sẽ là một trong những thứ để đi. Bạn rõ ràng đang nhận được một kho lưu trữ (hoặc lưu nó vào một tập tin và giải nén nó có thể sẽ thất bại, ít nhất là nếu bạn giải nén bằng cách chạy một chương trình giải nén "chuẩn"). Bạn thực sự có thể giải nén nó trong bộ nhớ, bằng cách sử dụng ZipInputStream. –

2

Đó là về cú pháp scala:

def unzipByteArray(input: Array[Byte]): String = { 
    val zipInputStream = new ZipInputStream(new ByteArrayInputStream(input)) 
    val entry = zipInputStream.getNextEntry 
    IOUtils.toString(zipInputStream, StandardCharsets.UTF_8) 
} 
Các vấn đề liên quan