В Java вы можете просматривать содержимое вложенных zip-файлов, не раздувая родительский файл? - PullRequest
0 голосов
/ 04 января 2019

У меня есть zip-файл, который содержит zip-файлы (которые сами могут содержать zip-файлы).

parent.zip
|- child_1.zip
|  |- foo.txt
|
|- child_2.zip
|  |- bar.txt
|
|- baz.txt

Используя ZipFile, я могу получить ZipEntries родительского zip-файла и увидеть детей (child_1.zip, child_2.zip, baz.txt), но я не могу найти способ проверить содержимое этих дочерних zip (foo.txt, bar.txt) без надувания родительского zip.

Возможно ли это, или мне нужно надуть parent.zip?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Можно использовать zip файловую систему , используя jar: файл: протокол:

            URI uri = new URI(
                "jar:file:/home/.../.../external.zip!/.../internal.zip!/");
            Map<String, ?> env = new HashMap<>();
            try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
                Path rootPath2 = zipfs.getPath("/");
                Files.walk(rootPath2).forEach(p -> {
                    System.out.printf("Path %s%n", p.toString());
                });
            }

Для рекурсивного обходадолжен создать URI с добавленным "! /" и выполнить рекурсию самостоятельно.

Используя Files, можно копировать файлы в zip-файловую систему и обратно.(Здесь у меня есть некоторые сомнения.)

0 голосов
/ 04 января 2019

Это проблема не самих zip-файлов (хотя это ужасный формат), а API java.util.zip и, вероятно, zlib, с которым он обычно реализуется.

ZipFileтребует File, которое ему нравится на карте памяти.Если «файл» на самом деле является вложенной записью, она не будет запущена, если вы не скопируете ее или не позаботитесь о какой-то специфической для ОС уловке.

Если вложенный ZIP-файл сжимается во внешнем ZIP-архивефайл, произвольный доступ явно отсутствует.В любом случае вам понадобится другой API.Однако java.util.zip имеет ZipInputStream.Не рассматривайте это как InputStream - это типично странное расположение подтипов.Это позволяет вам выводить записи, даже если архив является сжатой записью внешнего файла.

(Примерно ZIP-файлы работают так: В конце файла находится центральный каталог. ЧтобыДля доступа к архиву в режиме произвольного доступа необходимо загрузить конец файла и прочитать его. Он содержит имена, длины и т. д., а также смещение для каждой записи в файле. Записи содержат имена, длиныи т. д., и фактическое содержимое файла. Нет, они не обязательно должны быть согласованными или иметь какую-либо корреляцию 1-1. Может также содержать другую ложь, такую ​​как неверная длина распакованного файла или -1. В любом случае, вы можетеигнорируйте центральный каталог и последовательно читайте записи.

JAR-файлы добавляют веселья, добавляя INDEX.LST и META-INF/manifest.mf в качестве первых записей файла. Первый содержит индекс, аналогичный центральномудиректории, но спереди, а не в конце. Последняя может содержать список файлов вместе с подписями. Исполняемые файлы zip и GIFAR (и япохоже, что ранее обнаруженные эквиваленты для продуктов Microsoft) могут иметь что-то напичканное перед почтовым индексом, так что вам придется пройти через него сзади.)

Небольшая демонстрационная программа.

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

interface Code {
    static void main(String[] args) throws Exception {
        ZipFile zipZip = new ZipFile("zip.zip.zip");
        ZipEntry zipEntry = zipZip.getEntry("zip.zip");
        if (zipEntry == null) {
            throw new Error("zip.zip not found");
        }

        InputStream zipIn = zipZip.getInputStream(zipEntry);
        ZipInputStream zip = new ZipInputStream(zipIn);
        for (;;) {
            ZipEntry entry = zip.getNextEntry();
            if (entry == null) {
                break;
            }
            System.err.println(entry.getName());
            new BufferedReader(new InputStreamReader(zip)).lines().forEach(l -> {
                System.err.println("> "+l);
            });
         }
    }
}
...