то есть он имеет какое-то неправильно разделенное статическое состояние. Не доказано, просто предупреждение.

я есть несколько общих вопросов относительно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, бла, бла. Мы решили, что результатом нашего экспорта должен быть файл 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)

Я измерил это просто перечисление файлов с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);

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

 rogerdpack02 мар. 2018 г., 17:27
Я догадываюсь, что ZipFile читает индекс zip, в то время как ZipInputStream «перебирает» весь файл zip, читая один файл за другим, FWIW.
Решение Вопроса

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

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

 Joel11 янв. 2011 г., 20:33
Я могу засвидетельствовать факт, что это не потокобезопасно, через болезненный опыт.
 Lachezar Balev11 янв. 2011 г., 19:05
Привет, StaxMan! Я только что проверил реализацию ZipFile $ ZipFileInputStream в JDK6. Это возвращается ZipFile.getInputStream У него есть синхронизация, хотя я действительно не знаю, насколько это надежно.
 StaxMan11 янв. 2011 г., 19:07
Да, я не могу точно сказать, что это не потокобезопасный. Еще одна опасная часть - базовая нативная библиотека zlib, которая, как я подозреваю, не является поточно-ориентированной.

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

Ваш ответ на вопрос