Конвертировать zip в магазине компрессионные
У меня есть zip-файл file.zip, который сжат. Есть ли способ изменить уровень сжатия файла для хранения (без сжатия).
Я написал и попробовал следующий код, и он работает, но я буду запускать его в среде, где память и хранилище будут ограничены, и может не хватить места. Я использую библиотеку zip4j.
Этот код извлекает входной zip-файл в папку,а затем перезаписывает его с уровнем сжатия хранилища. Проблема с этим заключается в том, что в какой-то момент выполнения в хранилище есть 3 копии zip, что является проблемой, поскольку пространство является ограничением.
try {
String zip = "input.zip";
final ZipFile zipFile = new ZipFile(zip);
zipFile.extractAll("dir");
File file = new File("dir");
ZipParameters params = new ZipParameters();
params.setCompressionMethod(Zip4jConstants.COMP_STORE);
params.setIncludeRootFolder(false);
ZipFile output = new ZipFile(new File("out.zip"));
output.addFolder(file, params);
file.delete();
return "Done";
} catch (Exception e) {
e.printStackTrace();
return "Error";
}
Итак, есть ли предложения по другому подходу к этой проблеме? Или, может быть, некоторые оптимизации скорости или памяти для моего текущего кода?
2 ответов:
В качестве альтернативы мы можем читать файлы из zip один за другим в памяти или во временный файл, как здесь
ZipInputStream is = ... ZipOutputStream os = ... os.setMethod(ZipOutputStream.STORED); int bSize = ... calculate max available size byte[] buf = new byte[bSize]; for (ZipEntry e; (e = is.getNextEntry()) != null;) { ZipEntry e2 = new ZipEntry(e.getName()); e2.setMethod(ZipEntry.STORED); int n = is.read(buf); if (is.read() == -1) { // in memory e2.setSize(n); e2.setCompressedSize(n); CRC32 crc = new CRC32(); crc.update(buf, 0, n); e2.setCrc(crc.getValue()); os.putNextEntry(e2); os.write(buf, 0, n); is.closeEntry(); os.closeEntry(); } else { // use tmp file } }Считывание в памяти должно быть быстрее
Я, наконец, получил его через несколько часов, играя с входными потоками.
Большое спасибо за ваш ответ Евгений Дорофеев, я буквально только что получил свой ответ, когда прочитал ваш! Однако я предпочитаю свой метод, поскольку он занимает не более 1 МБ памяти (я прав?). Кроме того, я попытался выполнить ваш код, и был передан только первый файл во входном zip-файле.try { final ZipFile zipFile = new ZipFile("input.zip"); File output = new File("out.zip"); byte[] read = new byte[1024]; ZipInputStream zis = new ZipInputStream(new FileInputStream(zip)); ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(output)); ZipEntry ze; zos.setLevel(ZipOutputStream.STORED); zos.setMethod(ZipOutputStream.STORED); while((ze = zis.getNextEntry()) != null) { int l; zos.putNextEntry(ze); System.out.println("WRITING: " + ze.getName()); while((l = zis.read(read)) > 0) { zos.write(read, 0, l); } zos.closeEntry(); } zis.close(); zos.close(); return "Done"; } catch (Exception e) { e.printStackTrace(); return "Error"; }
Comments