Java高效读取大文件

发表于:2015-1-20 09:14

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:进林    来源:51Testing软件测试网采编

  1、概述
  本教程将演示如何用Java高效地读取大文件。这篇文章是Baeldung (http://www.baeldung.com/) 上“Java——回归基础”系列教程的一部分。
  2、在内存中读取
  读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法:
  Files.readLines(new File(path), Charsets.UTF_8);
  FileUtils.readLines(new File(path));
  这种方法带来的问题是文件的所有行都被存放在内存中,当文件足够大时很快就会导致程序抛出OutOfMemoryError 异常。
  例如:读取一个大约1G的文件:
  @Test
  public void givenUsingGuava_whenIteratingAFile_thenWorks() throws IOException {
  String path = ...
  Files.readLines(new File(path), Charsets.UTF_8);
  }
  这种方式开始时只占用很少的内存:(大约消耗了0Mb内存)
  [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 128 Mb
  [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 116 Mb
  然而,当文件全部读到内存中后,我们最后可以看到(大约消耗了2GB内存):
  [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 2666 Mb
  [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 490 Mb
  这意味这一过程大约耗费了2.1GB的内存——原因很简单:现在文件的所有行都被存储在内存中。
  把文件所有的内容都放在内存中很快会耗尽可用内存——不论实际可用内存有多大,这点是显而易见的。
  此外,我们通常不需要把文件的所有行一次性地放入内存中——相反,我们只需要遍历文件的每一行,然后做相应的处理,处理完之后把它扔掉。所以,这正是我们将要做的——通过行迭代,而不是把所有行都放在内存中。
  3、文件流
  现在让我们看下这种解决方案——我们将使用java.util.Scanner类扫描文件的内容,一行一行连续地读取:
FileInputStream inputStream = null;
Scanner sc = null;
try {
inputStream = new FileInputStream(path);
sc = new Scanner(inputStream, "UTF-8");
while (sc.hasNextLine()) {
String line = sc.nextLine();
// System.out.println(line);
}
// note that Scanner suppresses exceptions
if (sc.ioException() != null) {
throw sc.ioException();
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (sc != null) {
sc.close();
}
}
  这种方案将会遍历文件中的所有行——允许对每一行进行处理,而不保持对它的引用。总之没有把它们存放在内存中:(大约消耗了150MB内存)
  [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Total Memory: 763 Mb
  [main] INFO  org.baeldung.java.CoreJavaIoUnitTest - Free Memory: 605 Mb
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号