Какой идиоматический способ скопировать 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.