概要
Apache POIを使ってExcel出力をjavaで実装する際、XSSFWorkbookと比べてより処理の早いSXSSFWorkbookを使いました。
実際にSXSSFを使うまではSXSSFのストリーミング処理の動きがイメージしづらかったため、図を使って本記事にまとめました。
そもそもXSSFとSXSSFとは
XSSF
Excel 2007およびそれ以降のバージョンで使用されるOffice Open XML (OOXML)形式の.xlsxファイルを読み書きするためのAPI
SXSSF
大容量データを処理するために設計された、XSSFのストリーミング版
SXSSFはストリーミング形式により、順番にメモリ上の行データを破棄しながら処理を進めていくため、XSSFに比べて処理速度が速いです。ではどのタイミングでデータを破棄をするのか、SXSSFのストリーミング処理のイメージついて説明します。
SXSSFのストリーミング処理のイメージ
<環境情報>
javaバージョン:17
POIバージョン:5.2.3
SXSSFのデフォルトでは100行以上を書き込みした場合、先頭行から71行分をメモリから破棄します。ここで言う100行は連続していなくても問題ありません。
100行以上書き込みされた状態で、再度先頭行から71行目までにアクセスしようとするとエラーになってしまいます。
2024-04-09T19:11:03.579+09:00 ERROR 31191 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalArgumentException: Attempting to write a row[9] in the range [0,921] that is already written to disk.] with root cause
java.lang.IllegalArgumentException: Attempting to write a row[9] in the range [0,921] that is already written to disk.
at org.apache.poi.xssf.streaming.SXSSFSheet.createRow(SXSSFSheet.java:139) ~[poi-ooxml-5.2.3.jar:5.2.3]
at org.apache.poi.xssf.streaming.SXSSFSheet.createRow(SXSSFSheet.java:45) ~[poi-ooxml-5.2.3.jar:5.2.3]
デフォルトでは100行が上限ですが、SXSSFWorkbookクラスの第2引数で書き込み上限の行を指定することが可能です。
下図の設定では、10000行以上書き込みがされた時点で再度先頭行から71行目までがアクセスできなくなります。
おわりに
SXSSFを使う際はストリーミング処理のイメージが沸かないと先程紹介したjava.lang.IllegalArgumentExceptionのエラーに結構陥ってしまいます(私も苦戦しました…)
本記事が少しでも理解の手助けになれたら幸いです!