Это проблема не самих 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);
});
}
}
}