У 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:

  1. Стандартный шаблон JETT XLSX для генерации заголовков и форматирования. Последняя строка первого листа содержит ячейки с $$tokens$$, по одной на ячейку. Я не использую JETT для вставки большого количества строк.

  2. Как только JETT выполнил свою работу, я снова открыл книгу, прочитал, затем удалил $$ tokens $$ в последней строке первой электронной таблицы и начал потоковую передачу данных с SXSSF строка за строкой.

Конечно, у этого подхода есть ограничения: - Вы не можете использовать JETT ни для одной из потоковых строк во время вставки строк (но вы могли раньше, например, динамически выбирать порядок $$ tokens $$) - Формат Cells выиграл ' не будет скопировано, если вы сами не позаботитесь об этом с помощью POI API. Я лично предпочитаю форматировать целые столбцы в моем файле XLSX, и это будет применяться к потоковым данным.

Это также работает, если вы хотите отобразить диаграммы с использованием данных, вставленных с помощью SXSSF: вы можете определить именованный диапазон с помощью функций OFFSET и COUNTA, а затем создать сводную таблицу и сводную диаграмму, которые будут обновляться при открытии XLSX в Excel.

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