Tak, masz rację. Różnica między tymi dwiema implementacjami polega na tym, że wersja strumieniowa zapisuje dane bezpośrednio do strumienia i przechowuje co najwyżej określoną liczbę wierszy w pamięci (domyślna wartość to 100 i jest przechowywana w SXSSFWorkbook.DEFAULT_WINDOW_SIZE). Z tego powodu po zapisaniu do strumienia wyjściowego nie będzie można uzyskać danych wiersza. Dużą korzyścią z używania implementacji strumienia jest mniejsze zużycie pamięci. Jeśli chcesz wyeksportować dużo danych, po prostu użyj SXSSFWorkbook.
Przykład:
public static void main(String[] args) throws IOException {
FileOutputStream inMemoryOut = new FileOutputStream(new File("inMemoryWorkbook.xlsx"));
XSSFWorkbook workbook = new XSSFWorkbook();
WorkbookExample example = new WorkbookExample(workbook, inMemoryOut);
example.export();
FileOutputStream streamOut = new FileOutputStream(new File("streamWorkbook.xlsx"));
SXSSFWorkbook streamWorkbook = new SXSSFWorkbook();
WorkbookExample streamExample = new WorkbookExample(streamWorkbook, streamOut);
streamExample.export();
}
public class WorkbookExample {
private Logger logger = Logger.getLogger(WorkbookExample.class.getName());
private Workbook workbook;
private OutputStream out;
public WorkbookExample(Workbook workbook, OutputStream out) {
this.workbook = workbook;
this.out = out;
}
public void export() throws IOException {
logger.info("export start for " + workbook.getClass().getName());
List<Person> persons = new ArrayList<Person>();
for (int i = 0; i < 1000; i++) {
persons.add(new Person(String.valueOf("user_" + i)));
}
Sheet sheet = workbook.createSheet();
for (int i = 0; i < persons.size(); i++) {
Person p = persons.get(i);
Row row = sheet.createRow(i);
Cell cell = row.createCell(0);
cell.setCellValue(p.getName());
}
workbook.write(out);
logger.info("Is row 1 accessible after writing to output stream? " + String.valueOf(sheet.getRow(1) != null));
out.close();
workbook.close();
logger.info("export finished for " + workbook.getClass().getName());
}
public static class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
wyjściowa:
kwi 21, 2015 7:56:14 PM pepuch.html2pdf.WorkbookExample export
INFO: export start for org.apache.poi.xssf.usermodel.XSSFWorkbook
kwi 21, 2015 7:56:15 PM pepuch.html2pdf.WorkbookExample export
INFO: Is row 1 accessible after writing to output stream? true
kwi 21, 2015 7:56:15 PM pepuch.html2pdf.WorkbookExample export
INFO: export finished for org.apache.poi.xssf.usermodel.XSSFWorkbook
kwi 21, 2015 7:56:15 PM pepuch.html2pdf.WorkbookExample export
INFO: export start for org.apache.poi.xssf.streaming.SXSSFWorkbook
kwi 21, 2015 7:56:15 PM pepuch.html2pdf.WorkbookExample export
INFO: Is row 1 accessible after writing to output stream? false
kwi 21, 2015 7:56:15 PM pepuch.html2pdf.WorkbookExample export
INFO: export finished for org.apache.poi.xssf.streaming.SXSSFWorkbook
Jak widać rząd 1 nie jest dłużej dostępny po wpisaniu do strumienia wyjściowego z SXSSFWorkbook.
Dziękuję za odpowiedź, ale faktycznie zadawałem zupełnie inną. Zastanawiam się, czy moja istniejąca implementacja, która używa skoroszytu jako podstawy do tworzenia pliku xlsx, stanie się strumieniem, jeśli zacznę tworzyć skoroszyt przy użyciu klasy sxssfworkbook zamiast xssf. –
Jak napisałem, różnica polega na dostępności wierszy przechowywanych w skoroszycie. Jeśli nie potrzebujesz uzyskać wierszy po napisaniu do wyjścia steeam, możesz go użyć. – pepuch
@pepuch Tylko 'SXSSFWorkbook' ma metodę" dispose() ", używaną do usuwania plików tymczasowych. Jak dodać (lub nie) do klasy "WorkbookExample"? Odlew? Wystąpienie? –