У POI XSSF все еще есть проблемы с памятью?
Пару лет назад я столкнулся с проблемами, когда создавал большие файлы Excel, используя jXLS
а также POI XSSF
, Если моя память верна, я думаю XSSF
создаст что-то вроде 1 ГБ + временные файлы на диске для создания 10 МБ файлов Excel. Поэтому я перестал использовать jXLS
и вместо этого используется SXSSF
для создания файлов Excel, но сегодня у меня есть новые причины для использования jXLS
или же JETT
,
И то и другое jXLS
а также JETT
веб-сайты, кажется, намекают, что производительность намного лучше, но POI
"s XSSF
сайт по-прежнему говорит в общем, что XSSF
требует большего объема памяти. Я задаюсь вопросом, является ли этот более высокий объем памяти чем-то вроде разумных 10% -ых накладных расходов в наши дни, или же он по-прежнему равен 10 000% -ным накладным расходам, как это было пару лет назад.
Исправлены ли сумасшедшие проблемы с памятью в POI 3.9? XSSF
? Должен ли я не беспокоиться об использовании его с jXLS
или же JETT
? Или есть определенные ошибки, которых следует избегать? Я осторожен в повторном использовании стилей ячеек.
1 ответ
Чтобы ответить на ваш вопрос, да, POI всегда будет использовать очень большой объем памяти при работе с большими файлами XLSX, который намного больше, чем размер файлов XLSX. Я не думаю, что это скоро изменится, и для этого есть довольно очевидные причины: XLSX - это, по сути, набор сжатых XML-файлов, а XML очень хорошо сжат (примерно в 10 раз). Получение этого XML только для того, чтобы сидеть в несжатой памяти, уже увеличило бы потребление памяти в десять раз, поэтому, если вы добавите все накладные расходы на структуры данных, вы не сможете ожидать увеличения потребления памяти на 10% по сравнению с размером файла XLSX.
Хорошая новость заключается в том, что, как уже упоминалось в комментариях, Apache POI представил SXSSF для потоковой передачи очень большого объема данных в электронной таблице с очень хорошей производительностью и низким использованием памяти. Файлы XLSX, сгенерированные таким образом, по-прежнему передаются на жесткий диск, где они могут занимать довольно много места, но, по крайней мере, вы не рискуете OOME при записи сотен тысяч строк.
Проблема для вас в том, что вы не сможете заставить JETT напрямую работать с SXSSF, так как для заполнения шаблона требуется весь документ, загруженный в память. Автор JETT быстро обсудил эту тему здесь.
У меня была та же проблема, и в итоге я сделал двухэтапное создание XLSX:
Стандартный шаблон JETT XLSX для генерации заголовков и форматирования. Последняя строка первого листа содержит ячейки с $$tokens$$, по одной на ячейку. Я не использую JETT для вставки большого количества строк.
Как только JETT выполнил свою работу, я снова открыл книгу, прочитал, затем удалил $$ tokens $$ в последней строке первой электронной таблицы и начал потоковую передачу данных с SXSSF строка за строкой.
Конечно, у этого подхода есть ограничения: - Вы не можете использовать JETT ни для одной из потоковых строк во время вставки строк (но вы могли раньше, например, динамически выбирать порядок $$ tokens $$) - Формат Cells выиграл ' не будет скопировано, если вы сами не позаботитесь об этом с помощью POI API. Я лично предпочитаю форматировать целые столбцы в моем файле XLSX, и это будет применяться к потоковым данным.
Это также работает, если вы хотите отобразить диаграммы с использованием данных, вставленных с помощью SXSSF: вы можете определить именованный диапазон с помощью функций OFFSET и COUNTA, а затем создать сводную таблицу и сводную диаграмму, которые будут обновляться при открытии XLSX в Excel.