将ZipEntry复制到新ZipFile的惯用方法是什么?

我正在编写一个工具来在DOCX文件中进行一些小文本替换,这是一种压缩格式。 我的方法是使用ZipOutputStreamZipEntry内容从原始文件中的条目复制到修改后的文件中。 对于大多数DOCX文件,这种方法很有效,但偶尔我会遇到ZipException有关我写的内容与ZipEntry包含的元信息之间的差异(通常是压缩大小的差异)。

这是我用来复制内容的代码。 为简洁起见,我删除了error handling和文档处理; 到目前为止,我还没有遇到过文档条目的问题。

 ZipFile original = new ZipFile(INPUT_FILENAME); ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(OUTPUT_FILE)); Enumeration entries = original.entries(); byte[] buffer = new byte[512]; while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry)entries.nextElement(); if ("word/document.xml".equalsIgnoreCase(entry.getName())) { //perform special processing } else{ outputStream.putNextEntry(entry); InputStream in = original.getInputStream(entry); while (0 < in.available()){ int read = in.read(buffer); outputStream.write(buffer,0,read); } in.close(); } outputStream.closeEntry(); } outputStream.close(); 

ZipEntry对象从一个ZipFile直接复制到另一个ZipFile的正确或惯用方法是什么?

我找到了一个避免错误的解决方法。 通过创建一个只有名称字段集的新ZipEntry ,我可以无问题地复制内容。

 ZipFile original = new ZipFile(INPUT_FILENAME); ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(OUTPUT_FILE)); Enumeration entries = original.entries(); byte[] buffer = new byte[512]; while (entries.hasMoreElements()) { ZipEntry entry = (ZipEntry)entries.nextElement(); if ("word/document.xml".equalsIgnoreCase(entry.getName())) { //perform special processing } else{ // create a new empty ZipEntry ZipEntry newEntry = new ZipEntry(entry.getName()); // outputStream.putNextEntry(entry); outputStream.putNextEntry(newEntry); InputStream in = original.getInputStream(entry); while (0 < in.available()){ int read = in.read(buffer); outputStream.write(buffer,0,read); } in.close(); } outputStream.closeEntry(); } outputStream.close(); 

但是,我这种方法丢失了存储在原始ZipEntry字段中的任何元信息(例如:comment,extra)。 API文档不清楚这是否重要。

要保留zip条目的元数据,请使用ZipEntry的“复制构造函数”创建它:

 ZipEntry newEntry = new ZipEntry(entry); 

然后,您可以只修改名称或注释等,其他所有内容都将从给定entry复制。

您还可以查看可以从Java填充DocX文件的Docmosis。