При использовании ZipOutputStream для создания файла ODT в java не удается открыть в OpenOffice

У меня есть следующий метод добавления zip-записей в ZipOutputStream:

    private void addFile(String filename, byte[] bytes, ZipOutputStream zos, boolean encrypt) throws IOException {
        ZipEntry entry = new ZipEntry(filename);
        if (encrypt) {
            entry.setMethod(ZipEntry.DEFLATED);
        } else {
            entry.setMethod(ZipEntry.STORED);
            CRC32 crc32 = new CRC32();
            crc32.update(bytes);
            entry.setCrc(crc32.getValue());
            entry.setSize(bytes.length);
            entry.setCompressedSize(bytes.length);
        }
        zos.putNextEntry(entry);
        zos.write(bytes);
        zos.flush();
        zos.closeEntry();
    }

... и я использую его, открывая новый ZipOutputStream (ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(new File(path))));), устанавливая для его метода значение DEFLATED (zos.setMethod(ZipOutputStream.DEFLATED);), а затем вызывая следующие файлы (по порядку):

  1. "mimetype" (для этого файла я установил для метода ZipEntry значение STORED)
  2. «manifest.xml» в подпапке «META-INF» (META-INF/manifest.xml)
  3. "контент.xml"
  4. "стили.xml"
  5. "meta.xml"
  6. "thumbnail.png" во вложенной папке "Thumbnails" ("Thumbnails/thumbnail.png")
  7. "настройки.xml"

... наконец, я вызываю метод закрытия для ZipOutputStream (zos.close();).

Если я попытаюсь открыть его напрямую с помощью OpenOffice, он спросит меня, какой файл я пытаюсь открыть, скажет, что файл поврежден, и, наконец, откроет файл... но если я разархивирую файл (я с помощью winrar), а затем я снова заархивирую с помощью того же инструмента (я имею в виду winrar) без каких-либо изменений, OpenOffice может без проблем открыть документ...

Любая помощь? Заранее спасибо!


person raul_herranz    schedule 20.07.2012    source источник
comment
Это звучит немного странно. Обрабатываете ли вы исключения правильно?   -  person Stephen C    schedule 21.07.2012
comment
У меня есть большая попытка поймать весь код, и исключений нет.   -  person raul_herranz    schedule 21.07.2012
comment
Есть ли у вас какие-нибудь маленькие попытки перехвата исключений? (Я спросил, правильно ли вы обрабатываете исключения...)   -  person Stephen C    schedule 21.07.2012


Ответы (3)


Рауль,

Похоже, ваш zip-файл цел и верен, поэтому проблема не в процессе zip.

Проблема в том, что расположение doctype dtd неверно, когда ваш процесс создает файл xml для файла maniest.xml.

Строка в manifest.xml:

And also you have a manifest.rdf file in the root of the zip which throwing OO off when trying to put stuff back together. I don't know process you are using to create the OpenOffice document XML output, but thats where the problem is. You need to make sure the path for the DTD is correct or remove the DOCTYPE from the XML files.

Вот как вы можете вручную исправить файл OpenOffice ODT:

  • Удалите Manifest.rdf из корневого каталога zip.
  • Удалите строку DOCTYPE из META-INF/menifest.xml.
  • Добавьте записи манифеста для каталогов, перечисленных ниже (обратите внимание на разницу в записи Configurations2).

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/statusbar/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/current.xml"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/accelerator/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/floater/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/popupmenu/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/progressbar/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/toolpanel/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/menubar/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/toolbar/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/Bitmaps/"/>

    ‹ manifest:file-entry manifest:media-type="" manifest:full-path="Configurations2/images/"/>

‹ manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>

Я думаю, что winrar может позаботиться об устранении проблем с путем dtd для вас. И так же открывается офис, когда он его ремонтирует. ОО может справиться с отсутствием определения DTD, оно знает, что искать, но ему не нравятся плохие DTD.

Надеюсь, это исправит это для вас. Мне нравится знать, что вы используете для написания XML.

person Pareshkumar    schedule 23.07.2012
comment
Я отправил вам odt-файл, созданный с помощью OpenOffice, и odt-файл, созданный с помощью моего кода после кодирования ваших исправлений... как вы видите, есть некоторые различия в размере некоторых сжатых элементов... знаете почему? может проблема с реализацией java zip? - person raul_herranz; 27.07.2012

Я обнаружил, что проблема может быть в Windows, где вы указываете обратную косую черту в имени файла, который вы передаете конструктору ZipEntry. Я меняю их на косую черту, и после этого OpenOffice больше не жалуется на повреждение odt

person Bobs Dogs    schedule 14.02.2013

person    schedule
comment
И нужно ли создавать корневой каталог (/ или ./)? - person raul_herranz; 21.07.2012
comment
Имя zip-файла обычно не используется при распаковке zip. Вы можете создать zip и безопасно переименовать файл во что угодно, но при распаковке будет использоваться новое имя. Мы используем для добавления времени, обработки, состояния и того, чтобы имя файла отражало текущее состояние и историю в имени файла. - person Pareshkumar; 21.07.2012
comment
Удачи надеюсь, что вы можете пригвоздить его. Также это может не иметь значения, но у меня были проблемы, если я записывал все данные сразу, это блокирующий вызов, поэтому, если вы заархивируете изображение размером 200 МБ, ваше приложение может немного зависнуть. У меня никогда не было проблем после того, как я начал читать/писать 1024 байта за раз. - person Pareshkumar; 21.07.2012
comment
прямо сейчас я создаю следующие записи: · mimetype · Thumbnails/ · META-INF/ · META-INF/manifest.xml · content.xml · styles.xml · meta.xml · settings.xml · Thumbnails/thumbnail.png ... но у меня все еще та же проблема :( - person raul_herranz; 22.07.2012
comment
Я не нахожусь рядом со своим ноутбуком и не могу прокручивать свой код, но проверьте это, он хорош как есть, вы сможете использовать его как есть. Просто не забудьте получить файл mime в качестве первой записи. - person Pareshkumar; 22.07.2012
comment
О, я думаю, мне следует указать, что проверить: avajava.com/tutorials/lessons/ - person Pareshkumar; 22.07.2012
comment
О, и я не думаю, что вы должны записывать какие-либо байты или даже вызывать zip.write( bytes ) при обработке записи в каталоге. Как и в случае с выводом обуви из моих предыдущих образцов заархивированного содержимого, вам просто нужно убедиться, что пути являются относительными, и вы не перебираете свои записи с дополнительными или не предоставляете количество байтов, которое вы просите разместить при вызове записи. Если у вас нет каких-либо конфиденциальных данных в вашем документе oo, вы можете отправить по электронной почте почтовый индекс, которым вы закончили, и отправить его с исправлением, пытаясь открыть его. Пареш@kuyash.com - person Pareshkumar; 22.07.2012
comment
Да, и еще один быстрый способ, хотя ваш путь в виде строки, которую вы передаете ZipEntey (путь), это /home/user/you/content2compress/content.xml или это context.xml? Надеюсь, вы вырезаете все до каталога content2compress/, включая корневой каталог / after. Поэтому у вас не должно быть /content.xml в качестве имени zipEntey или переданного пути. - person Pareshkumar; 22.07.2012
comment
Я отправил вам образец файла odt, созданный с помощью моего кода... Если у вас есть идеи... Спасибо! - person raul_herranz; 23.07.2012
comment
@raul_herranz Хэй, у тебя все работает правильно? Я получил ваше первое электронное письмо, но я не видел второго электронного письма с новым файлом odt. Извините, я не следил за этим, был немного занят. - person Pareshkumar; 31.07.2012
comment
вот мой ответ на ваш вопрос, какой размер буфера вы используете для записи в свой zipoutputstream?: Я пробовал с разными размерами буфера: 1024, 2048, 4096 и с полными файлами без буферизации... и я всегда получаю такой же разный размер после архивирования файлов... - person raul_herranz; 02.08.2012