What is the idiomatic way to copy a ZipEntry into a new ZipFile?

删除回忆录丶 提交于 2019-12-08 11:46:26

问题


I'm writing a tool to do some minor text replacement in a DOCX file, which is a zipped format. My method is to copy ZipEntry contents from entries in the original file into the modified file using a ZipOutputStream. For most DOCX files this works well, but occasionally I will encounter ZipExceptions regarding discrepancies between the contents I've written and the meta-information contained in the ZipEntry (usually a difference in compressed size).

Here's the code I'm using to copy over contents. I've stripped out error handling and document processing for brevity; I haven't had issues with the document entry so far.

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

What is the proper or idiomatic way to directly copy ZipEntry objects from one ZipFile to another?


回答1:


I have found a workaround that avoids the error. By creating a new ZipEntry with only the name field set I'm able to copy over contents without issue.

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);
            if (read > 0) {
              outputStream.write(buffer,0,read);
            }
        }
        in.close();
    }
    outputStream.closeEntry();
}
outputStream.close();

However, I this method loses any meta-information stored in the fields of original ZipEntry (e.g.: comment, extra). The API docs aren't clear on whether this is important.




回答2:


To keep your meta-data for the zip entry, create it using ZipEntry's "copy constructor":

ZipEntry newEntry = new ZipEntry(entry); 

You can then modify just the name or the comments etc. and everything else will be copied from the given entry.

You could also look at Docmosis which can populate DocX files from Java.



来源:https://stackoverflow.com/questions/11766741/what-is-the-idiomatic-way-to-copy-a-zipentry-into-a-new-zipfile

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!