2012-08-01 164 views
0

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

这里是我用来复制内容的代码。为了简洁,我已经删除了错误处理和文档处理。到目前为止,我还没有遇到关于文档条目的问题。

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(); 

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

回答

6

我找到了避免错误的解决方法。通过创建一个只有名称字段集的新的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领域的任何元信息(例如:评论,多余的)。 API文档不清楚这是否重要。

+0

我已经标记了我的解决方法,因为似乎没有更好的答案。 – Keeblebrox 2012-08-14 14:45:53

0

为了让您的元数据的ZIP入口,使用的ZipEntry的“拷贝构造函数”来创建它:

ZipEntry newEntry = new ZipEntry(entry); 

然后,您可以只修改名称或评论等一切将来自被复制给出entry

你也可以看看Docmosis它可以从Java填充DocX文件。

+0

不幸的是,复制构造函数遭受我原来的问题,这是从原始复制的大小有不正确的压缩大小。我的解决方法是通过允许库自动设置大小,但不利于丢失元数据来避免这种情况。 Docmosis看起来像一个伟大的服务,感谢提高。 – Keeblebrox 2012-08-08 16:55:17

+1

只需添加一行:'newEntry.setCompressedSize(-1);',它就可以工作。 – xarx 2015-01-28 07:57:57

相关问题