Какой самый быстрый способ извлечь 1 файл из ZIP-файла, который содержит много файлов? - PullRequest
12 голосов
/ 30 марта 2011

Я пробовал пакет java.util.zip , он слишком медленный.

Потом я нашел LZMA SDK и 7z jbinding но им тоже чего-то не хватает. LZMA SDK не предоставляет своего рода документацию / руководство по использованию, это очень расстраивает. Нет Javadoc.

Хотя 7z jbinding не предоставляет простой способ извлечь только 1 файл, тем не менее, он предоставляет только способ извлечь все содержимое zip-файла. Более того, он не позволяет указать место для размещения разархивированного файла.

Любая идея, пожалуйста ???

Ответы [ 3 ]

15 голосов
/ 30 марта 2011

Как выглядит ваш код с java.util.zip и с каким размером zip-файла вы имеете дело?

Я могу извлечь запись размером 4 МБ из файла ZIP размером 200 МБ с 1800 записями впримерно секунда с этим:

OutputStream out = new FileOutputStream("your.file");
FileInputStream fin = new FileInputStream("your.zip");
BufferedInputStream bin = new BufferedInputStream(fin);
ZipInputStream zin = new ZipInputStream(bin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
    if (ze.getName().equals("your.file")) {
        byte[] buffer = new byte[8192];
        int len;
        while ((len = zin.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        out.close();
        break;
    }
}
11 голосов
/ 08 октября 2014

Я не тестировал скорость, но с помощью Java 7 или выше я извлекаю файл следующим образом.
Я полагаю, что это быстрее, чем ZipFile API:

Краткий пример извлечения META-INF/MANIFEST.MF из zip-файла test.zip:

// file to extract from zip file
String file = "MANIFEST.MF";
// location to extract the file to
File outputLocation = new File("D:/temp/", file);
// path to the zip file
Path zipFile = Paths.get("D:/temp/test.zip");

// load zip file as filesystem
try (FileSystem fileSystem = FileSystems.newFileSystem(zipFile, null)) {
    // copy file from zip file to output location
    Path source = fileSystem.getPath("META-INF/" + file);
    Files.copy(source, outputLocation.toPath());
}
6 голосов
/ 31 марта 2011

Используйте ZipFile вместо ZipInputStream .

Хотя в документации это не указано (в документации для JarFile), для чтения файла следует использовать файловые операции с произвольным доступом. Поскольку ZIP-файл содержит каталог в известном месте, это означает, что для поиска определенного файла требуется ОЧЕНЬ МНОГО IO.

Некоторые предостережения: насколько мне известно, реализация Sun использует файл с отображением в памяти. Это означает, что ваше виртуальное адресное пространство должно быть достаточно большим, чтобы вместить файл и все остальное в вашей виртуальной машине Java. Что может быть проблемой для 32-битного сервера. С другой стороны, он может быть достаточно умным, чтобы избежать отображения памяти в 32-разрядной системе или отображения карты памяти только в каталоге; Я не пробовал.

Кроме того, если вы используете несколько файлов, обязательно используйте try / finally, чтобы обеспечить закрытие файла после использования.

...