Java 8 和文件处理 30 MB excel

标签 java excel email

我的任务之一是只使用 Java 8如果需要,则仅 Spring ,基本上对这个项目有最小的依赖。

有一个可以增长的 30 MB 大小的 excel。这每天都会通过 FTP 出现,需要处理各个行,然后需要通过电子邮件发送最终报告。

现在我的问题是文件太大,请建议最好的方法来处理它而不会出现任何内存不足错误。

谢谢

最佳答案

读取文件行的​​标准方法是在内存中——Guava 和 Apache Commons IO 都提供了一种快速的方法来做到这一点:

Files.readLines(new File(path), Charsets.UTF_8);

FileUtils.readLines(new File(path));



这种方法的问题是所有文件行都保存在内存中——如果文件足够大,这将很快导致 OutOfMemoryError。
For example – reading a ~1Gb file:

@Test
public void givenUsingGuava_whenIteratingAFile_thenWorks() throws IOException {
    String path = ...
    Files.readLines(new File(path), Charsets.UTF_8);
}

这从消耗少量内存开始:(消耗约 0 Mb)
[main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 128 Mb
[main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 116 Mb

但是,在处理完完整文件后,我们最后得到:(消耗了约 2 Gb)
[main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb
[main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb

这意味着该进程消耗了大约 2.1 Gb 的内存——原因很简单——文件的行现在都存储在内存中。

此时应该很明显,将文件的内容保存在内存中将很快耗尽可用内存——不管实际有多少。

更重要的是,我们通常不需要一次将文件中的所有行都放在内存中——相反,我们只需要能够遍历每一行,进行一些处理并将其丢弃即可。所以,这正是我们要做的——在不保存内存的情况下遍历行。

使用 Apache Commons IO 进行流式传输

通过使用库提供的自定义 LineIterator 也可以使用 Commons IO 库来实现相同的目的:
LineIterator it = FileUtils.lineIterator(theFile, "UTF-8");
try {
    while (it.hasNext()) {
        String line = it.nextLine();
        // do something with line
    }
} finally {
    LineIterator.closeQuietly(it);
}

Since the entire file is not fully in memory – this will also result in pretty conservative memory consumption numbers: (~150 Mb consumed)


[main] INFO  o.b.java.CoreJavaIoIntegrationTest - Total Memory: 752 Mb
[main] INFO  o.b.java.CoreJavaIoIntegrationTest - Free Memory: 564 Mb

关于Java 8 和文件处理 30 MB excel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37878842/

相关文章:

Java不会改变变量

vba - Excel VBA错误恢复下一个返回值超出位置

vba - 如何根据 2 个单元格值在单元格中自动插入超链接

java - 使用 jSoup 将文本存储到字符串中

java - Linux 二进制文件应位于何处,以便在 PCF 中运行的 Spring Boot 微服务中通过 ProcessBuilder/Runtime 进行调用

javascript - 从 Javascript 发送邮件

android - 如何导入电子邮件附件?

android - 如何使用 authToken 发送电子邮件?

java - 如何使用java可调用接口(interface)异步处理队列项?

excel - 在列中显示行值