Какой идиоматический способ скопировать ZipEntry в новый ZipFile?

Я пишу инструмент для небольшой замены текста в файле DOCX, который находится в сжатом формате. Мой метод состоит в том, чтобы скопировать ZipEntry содержимое записей в исходном файле в измененный файл с помощью ZipOutputStream, Для большинства файлов DOCX это работает хорошо, но иногда я сталкиваюсь ZipExceptionо расхождениях между содержанием, которое я написал, и мета-информацией, содержащейся в 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{
        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 другому?

2 ответа

Решение

Я нашел обходной путь, который позволяет избежать ошибки. Создавая новый 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 не ясно, важно ли это.

Чтобы сохранить ваши метаданные для записи zip, создайте ее, используя "конструктор копирования" ZipEntry:

ZipEntry newEntry = new ZipEntry(entry); 

Затем вы можете изменить только имя или комментарии и т. Д., А все остальное будет скопировано из данного entry,

Вы также можете взглянуть на Docmosis, который может заполнять файлы DocX из Java.

Другие вопросы по тегам