2009-07-30 28 views
17

Tôi đang sử dụng gói tiện ích Zip của Java và muốn biết cách tạo tệp zip không nén. Đặt mức thành 0 không giúp ích gì. Thê nay đung không?Cách tạo lưu trữ Zip không nén trong Java

Ngoài ra, khi tôi sử dụng phương pháp STORED, nó throws sau ngoại lệ:

java.util.zip.ZipException: STORED entry missing size, compressed size, or crc-32 

tôi có thể thiết lập kích thước nhưng ngoại lệ tại đây là ném:

java.util.zip.ZipException: invalid entry crc-32 

Tôi chỉ sau tất cả các ví dụ có sẵn bằng cách tìm kiếm trên web và tôi không thể thực sự hiểu nó đúng cách tôi đoán. Nó sẽ là tuyệt vời nếu ai đó có thể giúp tôi về điều này và cung cấp cho tôi gợi ý để sửa vấn đề tôi có thể làm.

+0

Hằng số int đó là "mã giọng" từ một độ tuổi khác (có thể là C) ... Tôi ước David Connelly đã đọc về Java enums trước khi viết ZipOutputStream. –

+0

@ChristopheRoussy Điều đó sẽ khá khó khăn, vì 'ZipOutputStream' xuất hiện nhiều năm trước khi enums. – EJP

Trả lời

7

Bạn cần phải sử dụng phương pháp STORED, nhưng điều này đòi hỏi bạn phải thiết lập các size, compressedSizecrc32 thuộc tính của ZipEntry tương ứng trước khi bạn có thể gọi putNextEntry trên ZipOutputStream. Bạn có thể tính toán trước CRC-32 bằng cách sử dụng Crc32OutputStream.

+0

Cảm ơn bạn, có vẻ như bạn đã đúng, nhưng liệu có bất kỳ tài liệu nào không? – AlexWien

+1

Được chỉ định trong Đặc tả định dạng tệp ZIP tại https://www.pkware.com/documents/casestudies/APPNOTE.TXT. –

+1

@AlexWien Một lỗi sẽ được nâng lên bởi 'ZipOutputStream' nếu bạn không ... may mắn là nó có một thông báo lỗi tốt. –

11

Tôi rất lo lắng về giải pháp aperkins (kể từ khi xóa), nhưng tôi biết tại sao giải pháp này hoạt động. Điểm mấu (mà từ đó đã được khắc phục trong câu trả lời của ông)

zipOut.setLevel(ZipOutputStream.STORED); // accidentally right 

đã sử dụng giá trị tĩnh ZipOutputStream.STORED, mà tình cờ bằng 0. Vì vậy, những gì mà dòng đang làm là thiết lập mức được sử dụng bởi phương pháp DEFLATED mặc định để không nén (điều này rõ ràng là những gì bạn muốn làm, nhưng đã xảy ra để chỉ làm việc bằng may mắn). Vì vậy, để có được những gì bạn muốn một cách rõ ràng và an toàn, sử dụng này để thay thế:

zipOut.setMethod(ZipOutputStream.DEFLATED); // this line optional 
zipOut.setLevel(0); 

hoặc

zipOut.setLevel(Deflater.NO_COMPRESSION); 

Nếu bạn sử dụng

zipOut.setMethod(ZipOutputStream.STORED); 
zipOut.setLevel(Deflater.NO_COMPRESSION); 

có thể bạn sẽ có được ngoại lệ mà Keya lưu ý trong câu hỏi ban đầu. Tôi tin rằng Christian Schlichtherle là đúng; bạn đang nhận được các ngoại lệ vì bạn không đặt CRC trong mục nhập. Các hậu quả của việc đó là sử dụng phương pháp STORED, bạn phải đọc toàn bộ tệp nhập trước hoặc tìm cách khác để đặt kích thước, kích thước nén (phải bằng) và CRC trước khi gọi zipOut.putNextEntry(). Nếu không, bạn sẽ gặp phải nhiều ngoại lệ nếu bạn lạm dụng thuộc tính kích thước bằng cách viết quá nhiều byte vào luồng đầu ra. Có vẻ như các thông số ZIP nói rằng nếu bạn đang viết dữ liệu STORED thì nó phải viết tiêu đề [bao gồm CRC-32 và length] "lên phía trước" trước chính dữ liệu, do đó API java yêu cầu phải được đặt trước nó có thể bắt đầu, vì về cơ bản chỉ hỗ trợ phát trực tuyến ra tệp zip cuối cùng.

+2

DEFLATED + Level (0) dẫn đến trường hợp của tôi là ... MACHI TẬP TIN NÉN (A BIT) LỚN MỌI TƯƠNG LAI NGUỒN: O Tôi khá chắc chắn DEFLATED-0 khác với STORE:/ –

+2

DEFLATED-0 and STORE _might_ khác nhau, nhưng chúng có cùng mục tiêu - một tệp nén chứa dữ liệu không nén. Tôi không nghĩ rằng một trong hai phương thức sẽ xuất ra một tệp có kích thước bằng nhau với tệp nguồn. Tuy nhiên, trong câu hỏi, Keya đã gặp sự cố khi sử dụng phương pháp STORE, vì việc xử lý trước được yêu cầu để có được các đối số bắt buộc. Nếu bạn muốn một tệp nén nhỏ hơn tệp nguồn, hãy sử dụng một giá trị khác trong setLevel() - nhưng đó không phải là câu hỏi được yêu cầu. – PMorganCA

4

FYI:

Trong JDK Nguồn của phương pháp [java.util.zip.ZipOutputStream.setLevel (int)]:

public void setLevel(int level) { 
    def.setLevel(level); 
} 

Nó chỉ đơn giản chuyển hướng các thiết lập mức độ nén vào biến lĩnh vực [ def], là một thể hiện của [java.util.zip.Deflater].

Và trong mã nguồn của lớp [java.util.zip.Deflater]:

/** 
* Compression level for no compression. 
*/ 
public static final int NO_COMPRESSION = 0; 

/** 
* Compression level for fastest compression. 
*/ 
public static final int BEST_SPEED = 1; 

/** 
* Compression level for best compression. 
*/ 
public static final int BEST_COMPRESSION = 9; 

/** 
* Default compression level. 
*/ 
public static final int DEFAULT_COMPRESSION = -1; 

Vì vậy, tôi nghĩ rằng nó sẽ dễ đọc hơn nếu bạn sử dụng các giá trị không đổi [Deflater.NO_COMPRESSION]: