Apache POI SXSSF and XSSF

2019-04-28 06:46发布

问题:

I have one question. Am I right that if I have a workbook which is created through xssf constructor then it is enough to change the constructor to sxssf workbook (with xssf wb passed as an argument) to make it work in a stream mode? Thanks a lof for your answers.

Solution: It all depends on the classes which you use for streaming. If your class gathers more stream buffers than it can hold, this thing won't work. Otherwise it will

回答1:

Yes, you're right. The difference between these two implementations is that stream version writes data directly to stream and stores at most specified number of rows in memory (default value is 100 and it's stored in SXSSFWorkbook.DEFAULT_WINDOW_SIZE). Because of that you won't be able to get some row data after writing to output stream. Big benefit of using stream implementation is less memory usage. If you need to export a lot of data just use SXSSFWorkbook.

Example:

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;
        }

    }

}

Output:

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

As you see row 1 is not accessible any more after writing to output stream with SXSSFWorkbook.