编写巨大的 excel 文件(20k 条)需要超过 1 分钟的 java?

Writing huge excel file(20k records) is taking more then 1 minute java?

提问人:Gopi Lal 提问时间:7/9/2020 更新时间:12/22/2021 访问量:437

问:

嗨,我正在使用 apache POI 并写入工作簿,我正在使用 SXSSFWorkbook,因为数据会很大,

Eveything 看起来不错,但是在将工作簿转换为输入流时,导出报告需要花费大量时间。

这是我的代码

public StreamedContent generateStreamRep(String fileName, Workbook wb) {
    try (ByteArrayOutputStream dsf = new ByteArrayOutputStream();){     
        wb.write(dsf);      
        file = new DefaultStreamedContent(ByteSource.wrap(dsf.toByteArray()).openStream(), "xlsx", fileName);
   }

我正在使用 IOUtils 现在切换到 com.google.common.io.ByteSource

研究了 PipedStreams,但没有获得适当的资源。

Java Excel Stream Apache-POI IOstream

评论

2赞 Axel Richter 7/9/2020
如果没有一个完整的例子,这类问题就无法回答。请参阅 stackoverflow.com/questions/61221133/...。在那里,我提供了一个这样的,并且还告诉了我的结果。
0赞 Joop Eggen 7/9/2020
Java 管道 I/O(需要额外的线程)将是理想的选择。但是,添加足够大的初始容量也会有所帮助:. 可能不会改善事情。new ByteArrayOutputStream(10_000_000)openBufferedStream
0赞 Tarik 7/9/2020
如果有足够的内存,请使用内存流,然后将内存流的内容转储到文件中。我在处理 DB4 文件的库中遇到了这种问题。它避免了连续命中操作系统以执行 IO 操作。

答:

1赞 Spyros K 7/9/2020 #1

最小可重复示例将有助于提供更完整的答案。

但是,以下代码使用 PipedStreams 来加速问题代码中所示的操作。但是,您从此方法获得的好处不能大于 2 个并行进程中最快的一个。或者,换一种说法,最终持续时间不能快于并行操作的较慢持续时间。 在 PipedStreams 方法中,您需要 2 个流。 一个 PipedOutputStream,其中将写入数据,一个 PipedInputStream 是数据将被使用。 若要从此方法中受益,需要并行运行这两个操作。

public StreamedContent generateStreamRep(final String fileName, final Workbook wb) {
    try (final PipedOutputStream dsf = new PipedOutputStream ();
         final PipedInputStream sink=new PipedInputStream (dsf);){     

        final ExecutorService executorService= Executors.newSingleThreadExecutor();

        //Write to output stream
        executorService.execute(()->wb.write(dsf));

       //read from input stream
       file = new DefaultStreamedContent(sink, "xlsx", fileName);

        executorService.shutdown();

         //wait until task is finished or until a maximum time, which ever comes first. Normally in this case the task is already finished
        executorService.awaitTermination(2,TimeUnit.Minutes);
  

   }

评论

0赞 Gopi Lal 7/10/2020
它抛出异常,说管道已关闭!
0赞 Spyros K 12/22/2021
如果你能创建一个最小的可重复的例子,我可以检查一下。目前,此方法旨在成为使用示例。