Работа с Zip и GZip файлами в Java

Прошло некоторое время с тех пор, как я сделал Java I/O, и я не знаю последних "правильных" способов работы с Zip и GZip файлами. Мне не обязательно нужна полная рабочая демонстрация - я в первую очередь ищу подходящие интерфейсы и методы для использования. Да, я мог бы найти какой-либо случайный учебник по этому вопросу, но производительность - это проблема (эти файлы могут быть довольно большими), и мне действительно нужно использовать лучший инструмент для работы.

Основной процесс, который я буду выполнять:

  • Загрузите кучу файлов (которые могут быть сжаты в zip, gzipped или оба) в папку temp.
  • Добавьте все извлеченные файлы в новый zip файл в папке temp.

Входные файлы могут быть сжаты и архивированы более одного раза. Например, "полное извлечение" должно принимать любой из следующих входов (я не контролирую их) и оставляю foo.txt:

  • foo.txt.gz
  • foo.txt.zip
  • foo.txt.gz.zip
  • foo.txt.zip.gz
  • ...
  • foo.txt.gz.gz.gz.zip.gz.zip.zip.gz.gz
  • ...

Тогда мне могут быть оставлены foo.txt, bar.mp3, baz.exe - поэтому я просто добавлю их все в новый zip файл с каким-то общим именем.

Вопросы:

  • С размером файла, представляющим потенциальную проблему, который (интерфейсы/классы/методы) следует использовать для быстрого:
    • извлечь zip файлы?
    • извлечь gzip файлы?
    • написать zip файлы?
  • Мне лучше сохранить отдельные извлеченные файлы в памяти перед тем, как записать обратно на диск? Или,
  • Разве потенциально большие файлы делают эту плохую идею?

Ответы

Ответ 1

Обратите внимание, что библиотека TrueZip, предложенная ниже, была заменена на TrueVFS.


Я нашел полезную TrueZIP library. Он позволяет обрабатывать архивные файлы, как если бы они были просто другой файловой системой и использовать знакомые API-интерфейсы ввода-вывода Java.

В отличие от java.util.zip API, TrueZIP предоставляет произвольный доступ к содержимому архива, поэтому размер файла не должен вызывать беспокойства. Если я правильно помню, он будет обнаруживать архивные файлы и не пытаться избыточно сжимать их, когда вы помещаете их в архив.

Цитирование страницы TrueZIP:

API TrueZIP предоставляет замены для замены известных классов File, FileInputStream и FileOutputStream. Эта конструкция делает TrueZIP очень простой в использовании: все, что требуется для архивации большинства клиентских приложений, заключается в том, чтобы добавить несколько операторов импорта для пакета de.schlichtherle.io и добавить необходимые типы.

Теперь вы можете просто адресовать архивные файлы, такие как каталоги в имени пути. Например, имя пути "archive.zip/readme" обращается к записи архива "readme" в ZIP-архиве "archive.zip". Обратите внимание, что суффиксы имен файлов полностью настраиваются, и TrueZIP автоматически обнаруживает ложные срабатывания и возвращается назад, чтобы рассматривать их как обычные файлы или каталоги. Это работает рекурсивно, поэтому файл архива может быть даже заключен в другой файл архива, например, в "outer.zip/inner.zip/readme".

Ответ 2

Не сохраняйте все несжатые данные в памяти, или вы можете вырваться из кучи. Вам необходимо передать данные в файл при распаковке, а затем передать его обратно из файла, когда вы хотите создать свой последний zip файл.

Я раньше не делал файлы с zip файлами, но вот пример, который показывает, как распаковать gzipped файл:

import java.io.*;
import java.util.zip.*;

//unzipping a gzipped file
GZIPInputStream in = null;
OutputStream out = null;
try {
   in = new GZIPInputStream(new FileInputStream("file.txt.gz"));
   out = new FileOutputStream("file.txt");
   byte[] buf = new byte[1024 * 4];
   int len;
   while ((len = in.read(buf)) > 0) {
       out.write(buf, 0, len);
   }
}
catch (IOException e) {
   e.printStackTrace();
}
finally {
   if (in != null)
       try {
           in.close();
       }
       catch (IOException ignore) {
       }
   if (out != null)
       try {
           out.close();
       }
       catch (IOException ignore) {
       }
}

Ответ 3

Там может быть библиотека где-то, чтобы сделать это легко.

Однако, если этого не происходит, вы все равно можете сделать это с помощью классов java.util.zip... используя ZipFile или ZipInputStream, вдоль с ZipEntry для zip.

GZIPInputStream может обернуть FileInputStream для gzip, имея в виду, что gzip работает только с отдельными файлами.

Оба типа InputStreams также имеют соответствующие OutputStreams.

К сожалению, хотя я знаю об этих классах, я их никогда не использовал, поэтому я не могу советовать вам больше.

Изменить. У Zip-функций нет никакого способа добавления новых файлов в zip файл без повторного создания всего.