Solución:
Estaba en una situación similar con un entorno de servidor web. El tamaño típico de las cargas era ~ 150k filas y no habría sido bueno consumir una tonelada de memoria de una sola solicitud. La API de transmisión de puntos de interés de Apache funciona bien para esto, pero requiere un rediseño total de su lógica de lectura. Ya tenía un montón de lógica de lectura usando la API estándar que no quería tener que rehacer, así que escribí esto en su lugar: https://github.com/monitorjbl/excel-streaming-reader
No es un reemplazo completo del estándar. XSSFWorkbook
class, pero si solo está iterando a través de filas, se comporta de manera similar:
import com.monitorjbl.xlsx.StreamingReader;
InputStream is = new FileInputStream(new File("/path/to/workbook.xlsx"));
StreamingReader reader = StreamingReader.builder()
.rowCacheSize(100) // number of rows to keep in memory (defaults to 10)
.bufferSize(4096) // buffer size to use when reading InputStream to file (defaults to 1024)
.sheetIndex(0) // index of sheet to use (defaults to 0)
.read(is); // InputStream or File for XLSX file (required)
for (Row r : reader) {
for (Cell c : r) {
System.out.println(c.getStringCellValue());
}
}
Hay algunas advertencias para usarlo; Debido a la forma en que están estructuradas las hojas XLSX, no todos los datos están disponibles en la ventana actual de la secuencia. Sin embargo, si solo está tratando de leer datos simples de las celdas, funciona bastante bien para eso.
Se puede mejorar el uso de la memoria utilizando un archivo en lugar de una secuencia. (Es mejor usar una API de transmisión, pero las API de transmisión tienen limitaciones, consulte http://poi.apache.org/spreadsheet/index.html)
Entonces en lugar de
Workbook workbook = WorkbookFactory.create(inputStream);
hacer
Workbook workbook = WorkbookFactory.create(new File("yourfile.xlsx"));
Esto es de acuerdo con: http://poi.apache.org/spreadsheet/quick-guide.html#FileInputStream
Archivos vs InputStreams
“Al abrir un libro de trabajo, ya sea un .xls HSSFWorkbook o un .xlsx XSSFWorkbook, el libro de trabajo se puede cargar desde un archivo o un InputStream. El uso de un objeto File permite un menor consumo de memoria, mientras que un InputStream requiere más memoria, ya que para almacenar en búfer todo el archivo “.
POI ahora incluye una API para estos casos. SXSSF http://poi.apache.org/spreadsheet/index.html No carga todo en la memoria, por lo que podría permitirle manejar dicho archivo.
Nota: He leído que SXSSF funciona como una API de escritura. La carga debe realizarse usando XSSF sin inputstreaming el archivo (para evitar una carga completa en la memoria)