Подтвердить что ты не робот

Как создать несжатый архив ZIP в Java

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

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

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

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

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

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

4b9b3361

Ответ 1

Я обожаю решение 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

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

Ответ 3

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);