java.util.zip - ZipInputStream против ZipFile - PullRequest
7 голосов
/ 11 января 2011

У меня есть несколько общих вопросов, касающихся библиотеки java.util.zip. В основном мы занимаемся импортом и экспортом множества мелких компонентов. Ранее эти компоненты импортировались и экспортировались с использованием одного большого файла, например:

.
<component-type-a id="1"/>
<component-type-a id="2"/>
<component-type-a id="N"/>

<component-type-b id="1"/>
<component-type-b id="2"/>
<component-type-b id="N"/>

Обратите внимание, что порядок компонентов при импорте имеет значение.

Теперь каждый компонент должен занимать свой собственный файл, который должен иметь внешнюю версию, QA-ed, bla, bla. Мы решили, что результатом нашего экспорта должен быть файл zip (со всеми этими файлами), а вход нашего импорта должен быть похожим файлом zip. Мы не хотим взрывать почтовый индекс в нашей системе. Мы не хотим открывать отдельные потоки для каждого из маленьких файлов. Мои текущие вопросы:

Q1. Может ли ZipInputStream гарантировать, что записи zip (маленькие файлы) будут прочитаны в том же порядке, в котором они были вставлены нашим экспортом, использующим ZipOutputStream? Я предполагаю, что чтение что-то вроде:


ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
while((entry = zis.getNextEntry()) != null) 
{
       //read from zis until available
}

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

Q2. Если я использую ZipFile (что я предпочитаю), каково влияние на производительность вызова getInputStream() сотни раз? Будет ли это намного медленнее, чем решение ZipInputStream? Почтовый индекс открывается только один раз, а ZipFile поддерживается RandomAccessFile - это правильно? Я предполагаю, что чтение что-то вроде:


ZipFile zipfile = new ZipFile(argv[0]);
Enumeration e = zipfile.entries();//TODO: assure the order of the entries
while(e.hasMoreElements()) {
        entry = (ZipEntry) e.nextElement();
        is = zipfile.getInputStream(entry));
}

Q3. Безопасны ли входные потоки из одного потока ZipFile (например, могу ли я одновременно читать разные записи в разных потоках)? Какие-либо штрафы за производительность?

Спасибо за ваши ответы!

Ответы [ 3 ]

4 голосов
/ 11 января 2011

Q1: да, порядок, в котором были добавлены записи, будет таким же.

Q2: обратите внимание, что из-за структуры файлов zip-архивов и сжатия ни одно из решений не является потоковым; они все делают некоторый уровень буферизации. И если вы проверяете исходники JDK, реализации разделяют большую часть кода. Реального произвольного доступа к контенту нет, хотя индекс позволяет находить фрагменты, которые соответствуют записям. Поэтому я думаю, что не должно быть значимых различий в производительности; тем более что ОС все равно будет делать кеширование дисковых блоков. Вы можете просто протестировать производительность, чтобы проверить это с помощью простого тестового примера.

Q3: я бы на это не рассчитывал; и, скорее всего, это не так. Если вы действительно думаете, что одновременный доступ может помочь (в основном потому, что распаковка связана с процессором, поэтому это может помочь), я бы попробовал прочитать весь файл в памяти, открыть через ByteArrayInputStream и создать несколько независимых читателей.

2 голосов
/ 06 ноября 2013

Я измерял, что просто перечисление файлов с ZipInputStream в 8 раз медленнее, чем с ZipFile.

    long t = System.nanoTime();
    ZipFile zip = new ZipFile(jarFile);
    Enumeration<? extends ZipEntry> entries = zip.entries();
    while (entries.hasMoreElements())
    {
        ZipEntry entry = entries.nextElement();

        String filename = entry.getName();
        if (!filename.startsWith(JAR_TEXTURE_PATH))
            continue;

        textureFiles.add(filename);
    }
    zip.close();
    System.out.println((System.nanoTime() - t) / 1e9);

и

    long t = System.nanoTime();
    ZipInputStream zip = new ZipInputStream(new FileInputStream(jarFile));
    ZipEntry entry;
    while ((entry = zip.getNextEntry()) != null)
    {
        String filename = entry.getName();
        if (!filename.startsWith(JAR_TEXTURE_PATH))
            continue;

        textureFiles.add(filename);
    }
    zip.close();
    System.out.println((System.nanoTime() - t) / 1e9);

(Не запускайте иходин и тот же класс. Создайте два разных класса и запускайте их отдельно)

0 голосов
/ 17 июля 2013

Что касается Q3, опыт работы с JENKINS-14362 показывает, что zlib не является поточно-ориентированным даже при работе с несвязанными потоками , то есть что он имеет некоторое неправильно разделенное статическое состояние.Не доказано, просто предупреждение.

...