V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
goldpumpkin
V2EX  ›  程序员

请教大佬们,关于 Java 用 poi 的 SXSSFWorkbook 导出大量数据到 excel 文档,能否不生成临时文件,直接写入到响应流中呢

  •  
  •   goldpumpkin · 2020-06-08 18:50:29 +08:00 · 2516 次点击
    这是一个创建于 1627 天前的主题,其中的信息可能已经有所发展或是发生改变。
    11 条回复    2020-06-09 18:19:23 +08:00
    chendy
        1
    chendy  
       2020-06-08 18:53:14 +08:00
    有 write (或者叫 writeTo ?)方法,为啥还要写临时文件
    luckylo
        2
    luckylo  
       2020-06-09 06:58:33 +08:00 via Android
    可以的。如楼上所言。顺便提一句,当心内存问题
    fxxwor99LVHTing
        3
    fxxwor99LVHTing  
       2020-06-09 08:33:23 +08:00
    直接把字节数据写到 response 里面
    xuanbg
        4
    xuanbg  
       2020-06-09 08:52:55 +08:00
    为什么要生成临时文件?直接
    ```
    OutputStream stream = new FileOutputStream(file);
    workbook.write(stream);
    ```
    lqw3030
        5
    lqw3030  
       2020-06-09 08:56:34 +08:00
    当然可以,但是考虑到内存占用,SXSSFWorkbook 还特地提供了类似"滑动窗口"的机制
    goldpumpkin
        6
    goldpumpkin  
    OP
       2020-06-09 10:49:17 +08:00
    @chendy
    @luckylo
    谢谢回复。 其实我的目的是要 流式返回数据,在浏览器的表现是 用户点击完下载文件,后服务器一直返回数据给到浏览器。
    而 SXSSFWorkbook 是在服务器生成临时文件后后,点击下载文件,已下载下来的
    goldpumpkin
        7
    goldpumpkin  
    OP
       2020-06-09 10:59:25 +08:00
    @fxxwor99LVHTing
    @xuanbg
    谢谢回复。其实我想要的是增量输出到 outputstream 里面,我试了一下,不得行。
    ```
    try {
    ServletResponse responseAsync = asyncContext.getResponse();
    responseAsync.setCharacterEncoding("utf-8");

    List<List<String>> row = Arrays.asList(CollUtil.newArrayList("订单号", "渠道", "下班时间", "加班时长", "餐补", "车补次数", "车补", "总计"));
    ExcelWriter excelWriter = ExcelUtil.getBigWriter();
    excelWriter.write(row);
    excelWriter.flush(responseAsync.getOutputStream());

    responseAsync.getOutputStream().flush();

    for (int i = 0; i < 10; i++) {
    excelWriter.write(row);
    excelWriter.flush(responseAsync.getOutputStream());
    Thread.sleep(2000);
    }
    responseAsync.getOutputStream().flush();

    } catch (Exception e) {

    }
    ```
    wiix
        8
    wiix  
       2020-06-09 12:23:51 +08:00
    @luckylo
    @lqw3030
    实测调用 write()创不创建临时文件内存占用几乎一样,都很大。40 个字段,10W 行,要占用 1.5G 内存。
    想知道真正能节省内存的方法。
    lqw3030
        9
    lqw3030  
       2020-06-09 13:36:50 +08:00
    @goldpumpkin @wiix
    ```
    new SXSSFWorkbook(int windowSize)
    ```
    可以设置窗口大小,windowSize 即窗口保留行数
    goldpumpkin
        10
    goldpumpkin  
    OP
       2020-06-09 14:27:06 +08:00
    @wiix
    SXSSFWorkbook 就是为了防止内存溢出,才创建的临时文件。它有个窗口设置,超过这设置的行数(默认一百行),就写到临时文件里面,最后一起输出到流。
    @lqw3030
    是的,但是不没符合我的预期。我的预期是,数据分批次,多次 flush 到响应流里面,不生成临时文件。
    而 SXSSFWorkbook,如果不生成临时文件的话,会在内存操作的。
    xinQing
        11
    xinQing  
       2020-06-09 18:19:23 +08:00
    数据分批次从数据库查出,写入 response
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3051 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 13:38 · PVG 21:38 · LAX 05:38 · JFK 08:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.