Apache POI SXSSF and XSSF

7
我有一个问题。如果我有一个通过xssf构造函数创建的工作簿,那么只需将构造函数更改为带有xssf wb作为参数的sxssf工作簿,就可以使其在流模式下工作,我是否正确?感谢您的答案。
解决方案:这完全取决于您用于流式处理的类。如果您的类收集的流缓冲区多于它可以容纳的数量,则此方法将不起作用。否则,它会奏效。
1个回答

14
是的,你说得对。这两种实现之间的区别在于流版本直接将数据写入流并在内存中最多存储指定数量的行(默认值为100,并存储在SXSSFWorkbook.DEFAULT_WINDOW_SIZE中)。因此,写入输出流后,您将无法获取某些行数据。使用流实现的重大好处是更少的内存使用。如果需要导出大量数据,请使用SXSSFWorkbook。
示例:
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;
        }

    }

}

输出:

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

在使用SXSSFWorkbook写入输出流后,可以看到第一行已经不可访问了。


谢谢您的回复,但实际上我问的是完全不同的事情。我想知道如果我开始使用sxssfworkbook类而不是xssf来创建工作簿,那么我的现有实现是否可以将基础工作簿转换为流。 - Stepan Pogosyan
正如我所写的,区别在于工作簿中存储的行的可用性。如果您在写入输出流后不需要获取行,则可以使用它。 - pepuch
@pepuch 只有 SXSSFWorkbookdispose() 方法,用于删除临时文件。您会如何将其添加(或不添加)到 WorkbookExample 类中?强制转换?InstanceOf? - Rui Rebelo Brito
我可以知道何时避免使用SXSSF吗?因为它的好处很多,那么它的缺点是什么? - Raj Saraogi
1
据我理解,流式传输应该是逐步将数据写入磁盘。但在这个例子中,您在循环结束后才写入磁盘。整个文件的数据将保留在内存中,并一次性写入磁盘。这违背了流式传输的目的。 - Dojo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接