使用 Java 将文件追加到 zip 文件

2022-08-31 15:05:19

我目前正在提取war文件的内容,然后将一些新文件添加到目录结构中,然后创建一个新的war文件。

这一切都是从Java编程完成的 - 但我想知道复制war文件然后只是附加文件是否会更有效 - 那么我就不必等待战争扩大,然后必须再次压缩。

我似乎无法在文档或任何在线示例中找到执行此操作的方法。

任何人都可以提供一些提示或指示?

更新:

其中一个答案中提到的TrueZip似乎是一个非常好的java库,可以附加到zip文件中(尽管其他答案说不可能这样做)。

任何人都可以对TrueZip有经验或反馈,或者可以推荐其他类似的图书馆?


答案 1

在Java 7中,我们有Zip文件系统,允许在zip(jar,war)中添加和更改文件,而无需手动重新打包。

我们可以直接写入zip文件内的文件,如以下示例所示。

Map<String, String> env = new HashMap<>(); 
env.put("create", "true");
Path path = Paths.get("test.zip");
URI uri = URI.create("jar:" + path.toUri());
try (FileSystem fs = FileSystems.newFileSystem(uri, env))
{
    Path nf = fs.getPath("new.txt");
    try (Writer writer = Files.newBufferedWriter(nf, StandardCharsets.UTF_8, StandardOpenOption.CREATE)) {
        writer.write("hello");
    }
}

答案 2

正如其他人所提到的,不可能将内容附加到现有的zip(或战争)。但是,可以动态创建新的 zip,而无需临时将提取的内容写入磁盘。很难猜测这会快多少,但这是使用标准Java可以获得的最快的速度(至少据我所知)。正如Carlos Tasada所提到的,SevenZipJBindings可能会占用你一些额外的时间,但是将这种方法移植到SevenZipJBindings仍然比使用具有相同库的临时文件更快。

下面是一些代码,用于写入现有 zip (war.zip) 的内容,并将额外的文件(answer.txt)附加到新 zip(追加.zip)。只需要Java 5或更高版本,不需要额外的库。

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class Main {

    // 4MB buffer
    private static final byte[] BUFFER = new byte[4096 * 1024];

    /**
     * copy input to output stream - available in several StreamUtils or Streams classes 
     */    
    public static void copy(InputStream input, OutputStream output) throws IOException {
        int bytesRead;
        while ((bytesRead = input.read(BUFFER))!= -1) {
            output.write(BUFFER, 0, bytesRead);
        }
    }

    public static void main(String[] args) throws Exception {
        // read war.zip and write to append.zip
        ZipFile war = new ZipFile("war.zip");
        ZipOutputStream append = new ZipOutputStream(new FileOutputStream("append.zip"));

        // first, copy contents from existing war
        Enumeration<? extends ZipEntry> entries = war.entries();
        while (entries.hasMoreElements()) {
            ZipEntry e = entries.nextElement();
            System.out.println("copy: " + e.getName());
            append.putNextEntry(e);
            if (!e.isDirectory()) {
                copy(war.getInputStream(e), append);
            }
            append.closeEntry();
        }

        // now append some extra content
        ZipEntry e = new ZipEntry("answer.txt");
        System.out.println("append: " + e.getName());
        append.putNextEntry(e);
        append.write("42\n".getBytes());
        append.closeEntry();

        // close
        war.close();
        append.close();
    }
}

推荐