2009-07-30 1 views
17

Я использую пакет утилиты Zip Java и хотел знать, как создать zip-файл без сжатия вообще. Установка уровня на 0 не помогает. Это правильно?Как создать несжатый архив Zip в Java

Кроме того, когда я использовал метод STORED, он бросает следующее исключение:

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

я могу установить размер, но теперь следующее исключение:

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

Я просто следую все примеры доступны при поиске в Интернете, и я не могу понять это правильно, я думаю. Было бы здорово, если бы кто-то мог мне помочь в этом и предложил мне исправить проблему, которую я мог бы сделать.

+0

Эти постоянные являются «кодовым акцентом» из другого возраста (возможно, C) ... Я хочу, чтобы Дэвид Коннелли прочитал о переписках Java, прежде чем он написал ZipOutputStream. –

+0

@ ChristopheRoussy Это было бы довольно сложно, так как 'ZipOutputStream' появился за много лет до перечислений. – EJP

ответ

7

Вы должны использовать метод STORED, но это требует, чтобы вы установили size, compressedSize и crc32 свойства соответствующего ZipEntry перед вызовом putNextEntry на ZipOutputStream. Вы можете предварительно скопировать CRC-32 с помощью Crc32OutputStream.

+0

Спасибо, ты, кажется, прав, но это где-нибудь документировано? – AlexWien

+1

Он указан в спецификации формата ZIP-файла на странице https://www.pkware.com/documents/casestudies/APPNOTE.TXT. –

+1

@AlexWien Ошибка будет вызвана 'ZipOutputStream', если вы этого не сделаете ... к счастью, у него появилось хорошее сообщение об ошибке. –

11

Я нахожусь в aperkins Решение (после удаления), но я знаю, почему это сработало. Линия (которая впоследствии была исправлена ​​в своем ответе)

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

использовал статическое значение ZipOutputStream.STORED, который по совпадению приравнивает 0. Итак, что делает эта строка, установите уровень , используемый методом DEFLATED по умолчанию для нулевого сжатия (это, очевидно, то, что вы хотите сделать, но случилось только с удачей). Таким образом, чтобы получить то, что вы хотите явно и безопасно, используйте вместо этого:

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

или

zipOut.setLevel(Deflater.NO_COMPRESSION); 

Если вы используете

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

вы, вероятно, получите исключение, что Keya отмечено в оригинальный вопрос. Я считаю, Christian Schlichtherle прав; вы получаете Исключения, потому что вы не устанавливаете CRC в записи. Это связано с тем, что для использования метода STORED вам необходимо сначала прочитать весь файл записи или найти другой способ установить размер, сжатый размер (должен быть равен) и CRC, прежде чем вы вызовете zipOut.putNextEntry(). В противном случае вы столкнетесь с дополнительными исключениями, если вы превысите атрибут размера, записав слишком много байтов в выходной поток. Похоже, что в спецификациях ZIP говорят, что если вы записываете STORED-данные, тогда перед самими данными он должен записать заголовок [который включает в себя CRC-32 и длину] перед фронтом, поэтому API-интерфейс Java, требующий их, должен быть установлен перед ним может начаться, поскольку он в основном поддерживает только потоковое воспроизведение до последнего zip-файла.

+2

DEFLATED + Level (0) привел к тому, что мой случай ... КАЖДЫЙ СЖАТЫЙ ФАЙЛ (БИТ) БОЛЬШЕ, ЧЕМ ИСТОЧНИК ИСТОЧНИКА: O Я уверен, что DEFLATED-0 отличается от STORE:/ –

+2

DEFLATED-0 и STORE _might_ быть разными, но они имеют одинаковую цель - zip-файл, содержащий несжатые данные. Я не ожидаю, что любой из методов выдаст файл, равный по размеру исходному файлу. Однако в этом вопросе у Кейи возникла проблема с использованием метода STORE из-за предварительной обработки, необходимой для получения необходимых аргументов. Если вы хотите, чтобы сжатый файл был меньше исходного файла, используйте другое значение в setLevel() - но это не то, о чем просил этот вопрос. – PMorganCA

4

FYI:

В JDK Источник метода [java.util.zip.ZipOutputStream.setLevel (INT)]:

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

Это просто перенаправить настройку уровня сжатия с переменным полем [ def], который является экземпляром [java.util.zip.Deflater].

И в исходном коде класса [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; 

Так что, я думаю, что это будет более удобным для чтения, если вы используете постоянное значение [Deflater.NO_COMPRESSION]:

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