Работа с файлами Zip и GZip в Java - PullRequest
15 голосов
/ 14 сентября 2010

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

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

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

Входные файлы могут быть сжаты и заархивированы более одного раза.Например, «полное извлечение» должно принимать любой из следующих входных данных (я не контролирую их) и оставлять после себя 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?
  • Лучше ли мне хранить отдельные извлеченные файлы в памяти перед записью на диск?Или
  • Потенциально большие файлы делают эту идею плохой?

Ответы [ 3 ]

9 голосов
/ 14 сентября 2010

Не храните все эти несжатые данные в памяти, иначе у вас может не хватить места в куче. При распаковке вам необходимо передавать данные в файл, а затем возвращать их обратно из файла, когда вы хотите создать окончательный 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) {
       }
}
8 голосов
/ 14 сентября 2010

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


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

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

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

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

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

3 голосов
/ 14 сентября 2010

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

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

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

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

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

Редактировать: Функции Zip, по-видимому, не имеют какого-либо метода добавления новых файлов в zip-файл без воссоздания всего объекта.

...