Я хочу обновить файл внутри zip-архива без необходимости создавать новый архив. Я знаю, что это можно сделать, создав новый архив, скопировав все остальные файлы и добавив измененный в.
Вот код, демонстрирующий проблему. Первый раздел создает исходный zip-архив, содержащий один файл с содержимым Hello world!
. Второй раздел должен заменить этот контент на Bye, bye!
. В последнем разделе снова распаковывается zip-архив, поэтому можно ожидать, что содержимое будет:
try {
// Create the initial zip archive with the original file content
File file1 = new File(ReplaceFileInZipDemo.class.getResource("/helloworld.txt").toURI());
File zipFile = new File("output.zip");
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zipOut = new ZipOutputStream(fos);
FileInputStream fis = new FileInputStream(file1);
ZipEntry zipEntry = new ZipEntry(file1.getName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
fis.close();
zipOut.close();
fos.close();
// Replace the original file content with a different file content, updating the file.
File file2 = new File(ReplaceFileInZipDemo.class.getResource("/goodbyeworld.txt").toURI());
Path zipfile = zipFile.toPath();
FileSystem fs = FileSystems.newFileSystem(zipfile, null);
Path pathInZipfile = fs.getPath(file1.getName());
Files.copy(file2.toPath() , pathInZipfile, StandardCopyOption.REPLACE_EXISTING );
// Extract the content of the updated file
String destinationDir = System.getProperty("java.io.tmpdir");
File targetDir = new File(destinationDir);
ZipInputStream i = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry entry = null;
System.out.println("Original file content:");
Files.readAllLines(file1.toPath(), StandardCharsets.UTF_8).forEach(line -> System.out.println(line));
System.out.println("Expected replaced file content");
Files.readAllLines(file2.toPath(), StandardCharsets.UTF_8).forEach(line -> System.out.println(line));
while ((entry = i.getNextEntry()) != null) {
File destFile = new File(targetDir, entry.getName());
String name = destFile.getAbsolutePath();
File f = new File(name);
try (OutputStream o = Files.newOutputStream(f.toPath())) {
IOUtils.copy(i, o);
}
System.out.println("Content of extracted file " + name);
Files.readAllLines(f.toPath(), StandardCharsets.UTF_8).forEach(line -> System.out.println(line));
}
} catch (Exception e) {
e.printStackTrace();
}
Вывод, который я получаю, таков:
Original file content:
Hello world!
Expected replaced file content
Bye, bye!
Content of extracted file /tmp/helloworld.txt
Hello world!
Единственная причина, по которой я мог себе это представить не работает должным образом из-за того, что содержимое замены происходит из файла с другим именем, чем в архиве. Но при добавлении Files.delete(pathInZipfile);
для полного удаления исходного файла он все еще там.
Как заменить содержимое файла в архиве содержимым другого файла?