我的一个任务包括仅使用Java 8
,如果需要,那么只有Spring
,基本上对该项目的依赖性最小。Java 8和文件进程30 MB excel
有一个30 MB大小的excel可以增长。这通过FTP每天都会出现,需要处理单个行,然后最终报告需要通过电子邮件发送。
现在我的问题是文件太大,请建议最好的方式来处理它没有任何内存不足的错误。
感谢
我的一个任务包括仅使用Java 8
,如果需要,那么只有Spring
,基本上对该项目的依赖性最小。Java 8和文件进程30 MB excel
有一个30 MB大小的excel可以增长。这通过FTP每天都会出现,需要处理单个行,然后最终报告需要通过电子邮件发送。
现在我的问题是文件太大,请建议最好的方式来处理它没有任何内存不足的错误。
感谢
读取文件的行的标准方法是在内存中 - 无论是番石榴和Apache下议院IO提供了一种快速的方法来做到这一点:
Files.readLines(新文件(路径),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千兆消耗)
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb
[main] INFO org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb
这意味着大约2.1的存储器Gb的通过过程中消耗 - 的原因很简单 - 该文件的线路都被存储在存储器中现在。
在这一点上应该很明显的是,将文件内容保留在内存中将快速耗尽可用内存 - 无论实际内存多少。更重要的是,我们通常不需要立即在内存中存储文件中的所有行,相反,我们只需要遍历每一行,做一些处理并将其扔掉。所以,这正是我们要做的 - 在没有保存内存的情况下遍历行。
使用Apache共享IO流
同样可以使用Commons IO库以及来实现,通过使用由所述库提供的自定义LineIterator:
LineIterator it = FileUtils.lineIterator(theFile, "UTF-8");
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
LineIterator.closeQuietly(it);
}
由于整个文件没有完全在内存中 - 这也会导致 处于非常保守的内存消耗数字:(〜150 Mb被消耗)
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Total Memory: 752 Mb
[main] INFO o.b.java.CoreJavaIoIntegrationTest - Free Memory: 564 Mb
谢谢,我明白了,让我检查一下,如果它有效,我会检查它。:) –
@NotAvail如何使用Guava或Apache Commons IO符合您的要求以坚持使用Java 8或Spring? – SubOptimal
您的解决方案如何帮助处理大型Excel文件? – SubOptimal
你能有更多的信息吗?你尝试过什么(代码)?什么是例外信息等 – mnwsmit
Excel文件有什么问题?你有什么具体问题? – SubOptimal