2016-06-17 25 views
2

我的一个任务包括仅使用Java 8,如果需要,那么只有Spring,基本上对该项目的依赖性最小。Java 8和文件进程30 MB excel

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

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

感谢

+0

你能有更多的信息吗?你尝试过什么(代码)?什么是例外信息等 – mnwsmit

+0

Excel文件有什么问题?你有什么具体问题? – SubOptimal

回答

0

读取文件的行的标准方法是在内存中 - 无论是番石榴和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 
+1

谢谢,我明白了,让我检查一下,如果它有效,我会检查它。:) –

+0

@NotAvail如何使用Guava或Apache Commons IO符合您的要求以坚持使用Java 8或Spring? – SubOptimal

+0

您的解决方案如何帮助处理大型Excel文件? – SubOptimal