원문 링크: http://poi.apache.org/components/spreadsheet/how-to.html#sxssf
SXSSF는 org.apache.poi.xssf.streaming 패키지에 위치하며, XSSF와 호환性을 가지면서도 대용량 데이터 및 메모리 제약 상황을 해결할 수 있습니다. SXSSF는 특정 범위 내에서 행을 가져오며, 이 범위를 "슬라이딩 윈도우"라고 합니다. 이 윈도우 내의 데이터는 메모리에 존재하고, 윈도우 크기보다 큰 데이터는 디스크에 저장됩니다. 이는 XSSF가 전체 행을一次性로 가져오는 것과 대조적입니다.
이 "슬라이딩 윈도우"의 크기는 SXSSF 인스턴스를 생성할 때 다음과 같이 지정할 수 있습니다:
1 new SXSSFWorkbook(int windowSize)
SXSSFWorkbook.DEFAULT_WINDOW_SIZE는 기본 윈도우 크기로 100입니다. 윈도우 크기가 -1일 경우, 데이터를 디스크에 쓰는 작업은 flushRows() 메서드가 호출될 때까지 지연됩니다. 참고로, Excel 2003은 최대 65536개의 데이터를 저장할 수 있고, Excel 2007 이상 버전은 1048576개의 데이터를 지원합니다.
createRow() 메서드를 사용해 새로운 행을 생성하면 메모리 내의 윈도우 크기가 증가합니다. 윈도우 크기보다 많은 데이터가 생성되면, 가장 먼저 만들어진 행부터 차례대로 디스크에 쓰여집니다. 행이 디스크에 쓰이면 getRow() 메서드를 통해 해당 행을 다시 가져올 수 없습니다.
또한, SXSSF는 임시 파일을 자동으로 할당하며, 이 임시 파일은.dispose() 메서드를 통해 수동으로 삭제할 수 있습니다:
SXSSFWorkbook wb = new SXSSFWorkbook(100);<br>wb.dispose();
SXSSF는 기본적으로 인라인 문자(inline strings)를 사용합니다. 이는 유사한 문자를 서로 다른 문자로 취급하는 방식으로, 메모리 사용량을 절약하지만 호환성 문제를 일으킬 수 있습니다. 반면, 공유 문자(shared strings)는 중복 문자를 하나의 값으로 저장하지만, 모든 문자를 메모리에 미리 로딩해야 합니다.
셀 머지, 하이퍼링크, 댓글 등은 모두 메모리에 직접 저장됩니다. 따라서, 이러한 기능을 많이 사용하는 문서에서는 추가로 메모리를 사용할 수 있습니다.
다음은 윈도우 크기를 100으로 설정한示例입니다. 101번째 행부터는 차례대로 디스크에 쓰이며, 1000번째 행까지 생성 후, 900번째 이전의 행은 메모리에 없을 것입니다:
import junit.framework.Assert;<br>import org.apache.poi.ss.usermodel.Cell;<br>import org.apache.poi.ss.usermodel.Row;<br>import org.apache.poi.ss.usermodel.Sheet;<br>import org.apache.poi.ss.usermodel.Workbook;<br>import org.apache.poi.ss.util.CellReference;<br>import org.apache.poi.xssf.streaming.SXSSFWorkbook;<br><br>public static void main(String[] args) throws Throwable {<br> SXSSFWorkbook wb = new SXSSFWorkbook(100); // 메모리에 100개의 행 보관<br> Sheet sh = wb.createSheet();<br> for(int rowNum = 0; rowNum < 1000; rowNum++) {<br> Row row = sh.createRow(rowNum);<br> for(int cellNum = 0; cellNum < 10; cellNum++) {<br> Cell cell = row.createCell(cellNum);<br> String address = new CellReference(cell).formatAsString();<br> cell.setCellValue(address);<br> }<br> }<br><br> // 900개 이전의 행은 디스크에 저장됨<br> for(int rowNum = 0; rowNum < 900; rowNum++) {<br> Assert.assertNull(sh.getRow(rowNum));<br> }<br><br> // 마지막 100개의 행은 메모리에 보관됨<br> for(int rowNum = 900; rowNum < 1000; rowNum++) {<br> Assert.assertNotNull(sh.getRow(rowNum));<br> }<br><br> FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx");<br> wb.write(out);<br> out.close();<br><br> wb.dispose();
두 번째 示例에서는 자동 쓰기 기능을 关闭한 상태에서(윈도우 크기 -1로 설정) 수동으로 쓰기 시점을 제어하는 방법을 보여줍니다:
import org.apache.poi.ss.usermodel.Cell;<br>import org.apache.poi.ss.usermodel.Row;<br>import org.apache.poi.ss.usermodel.Sheet;<br>import org.apache.poi.ss.usermodel.Workbook;<br>import org.apache.poi.ss.util.CellReference;<br>import org.apache.poi.xssf.streaming.SXSSFWorkbook;<br><br>public static void main(String[] args) throws Throwable {<br> SXSSFWorkbook wb = new SXSSFWorkbook(-1); // 자동 쓰기 关闭<br> Sheet sh = wb.createSheet();<br> for(int rowNum = 0; rowNum < 1000; rowNum++) {<br> Row row = sh.createRow(rowNum);<br> for(int cellNum = 0; cellNum < 10; cellNum++) {<br> Cell cell = row.createCell(cellNum);<br> String address = new CellReference(cell).formatAsString();<br> cell.setCellValue(address);<br> }<br><br> // 수동 쓰기 제어<br> if(rowNum % 100 == 0) {<br> ((SXSSFSheet)sh).flushRows(100); // 마지막 100개의 행을 보관하고 나머지를 쓴다<br> // ((SXSSFSheet)sh).flushRows() 는 모든 행을 쓰는 기능을 제공함<br> }<br> }<br><br> FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx");<br> wb.write(out);<br> out.close();<br><br> wb.dispose();<br>}