Как создать несжатый Zip-архив на Java - PullRequest
20 голосов
/ 30 июля 2009

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

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

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

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

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

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

Ответы [ 3 ]

12 голосов
/ 01 декабря 2012

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

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

использовал статическое значение ZipOutputStream.STORED, которое по совпадению равно 0. Так что эта строка делает установку level , используемую стандартным методом 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);

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

7 голосов
/ 03 мая 2011

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

5 голосов
/ 23 октября 2014

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...