Обновление существующего файла Excel в Java Apache POI без использования InputStream

Я пытаюсь обновить существующий файл Excel (xlsx).

Конструкторы типа XSSFWorkbook(java.io.File file) и XSSFWorkbook(OPCPackage pkg) открывают файл в режиме только для чтения и не допускают изменений. Поэтому я должен использовать XSSFWorkbook(java.io.InputStream is), а объем памяти (память JVM и куча Java) слишком велик. Я не могу использовать аргументы VM для установки максимального размера памяти, так как я должен соблюдать требования к памяти других программ, работающих параллельно.

Использование SXSSFWorkbook было еще одним решением, но по сути это оболочка вокруг XSSFWorkbook. Те же проблемы сохраняются, что и с XSSFWorkbook.

Я пошел к другим сообщениям в SO и не смог найти подходящего ответа. Может ли кто-нибудь помочь мне с этим, пожалуйста? Я в порядке с хранением временных файлов.


person Gaurav    schedule 20.12.2019    source источник
comment
У меня были хорошие результаты (меньшее использование памяти) с использованием новой SXSSFWorkbook(-1) вместе с SXSSFSheet.flushRows(), но это было для создания нового файла, а не для его обновления. Я думаю, вам стоит попробовать SXSSFWorkbook   -  person Guillaume    schedule 20.12.2019


Ответы (1)


Ваш вопрос не ясен. На самом деле это не "Как открыть XSSFWorkbook без использования InputStream?" но "Как уменьшить объем памяти XSSFWorkbook?". И ответ на этот вопрос: Уменьшить нельзя, типа apache poi запрограммировано сейчас. В противном случае разработчики apache poi должны быть настолько глупы, что запрограммировали apache poi специально для того, чтобы тратить память. Они не.

Но используется слишком много уровней абстракции.

Все основано на XML. Но пользователи программных библиотек не хотят возиться с XML и, по крайней мере, с тем XML, который разбит на несколько файлов в ZIP-архиве, которые связаны друг с другом с помощью XML-файлов со специальными отношениями. Таким образом, помимо XML есть ooxml-schemas, библиотека, которая преобразует XML отдельных файлов в пригодные для использования java объекты. И есть org.apache.poi.openxml4j.opc.* для управления отношениями.

Чтобы получить все преимущества этого, все используемые java объекты (рабочая книга, листы, строки, ячейки, рисунки, таблицы, сводные таблицы, диаграммы...) и отношения между ними должны находиться в память должна быть готова к использованию. Или временные файлы должны использоваться для их временного хранения после извлечения их из ZIP-архива *.xlsx. На мой взгляд, работа непосредственно в файловой системе ZIP невозможна из-за поведения изменений в файловой системе такого типа.

Но использование временных файлов не предусмотрено apache poi. Только SXSSF использует временные файлы для рабочих листов, но только для записи новых файлов *.xlsx, а не для чтения и обновления таких файлов.

Кроме того, для максимальной совместимости с двоичным форматом файла BIFF *.xls добавлен еще один уровень. Это уровни SS и XSSF, которые обеспечивают классы высокого уровня apache poi. И из-за этого теперь есть дополнительные java объектов для рабочей книги, листов, строк, ячеек, рисунков, таблиц, сводных таблиц, диаграмм и т. д. в дополнение к низкоуровневым ooxml-schemas классам в памяти.

Итак... память заполнена, когда речь идет о больших *.xlsx файлах. ;-)

Решения?

Чтобы максимально сэкономить память, разархивируйте *.xlsx ZIP-архив и работайте непосредственно с XML в нем. Конечно, это очень трудоемко, особенно для создания нового контента и учета отношений. Я показал простые примеры для этого в своих ответах здесь. Например: Как для изменения большого файла Excel, когда не хватает памяти и Как установить цвет фона ячейки в Excel с помощью java + poi.

Или запрограммируйте расширение для apache poi, которое использует временные файлы вместо хранения всего в памяти. Конечно, это также трудоемко и имеет недостатки для систем, не предусматривающих использование временных файлов.

person Axel Richter    schedule 20.12.2019