将整个文件读入单个字符串而不是逐行读取有什么优缺点?

时间:2015-05-30 22:45:40

标签: java file-io java.util.scanner

具体来说,我的最终目标是在List<String>中存储文件中每个逗号分隔的单词,我想知道应采取哪种方法。

方法1:

String fileContents = new Scanner(new File("filepath")).useDelimiter("\\Z").next();
List<String> list = Arrays.asList(fileContents.split("\\s*,\\s*"));

方法2:

Scanner s = new Scanner(new File("filepath")).useDelimiter(",");
List<String> list = new ArrayList<>();
while (s.hasNext()){
    list.add(s.next());
}
s.close();

3 个答案:

答案 0 :(得分:2)

方法#1将整个文件读入内存。这有几个与性能相关的问题:

  • 如果文件很大,会占用大量内存。
  • 由于'/something/article.jsp?id=1787'电话需要累积角色的方式,角色可能需要复制2次甚至3次。
  • 由于您使用通用模式匹配引擎来实现非常特定的目的,因此存在其他效率低下的问题。

方法#3(方法#1,文件读取更好)解决了很多效率问题,但你仍然将整个文件内容保存在内存中。

方法#2最好从内存使用角度来看,因为您没有将整个文件内容保存为单个字符串或缓冲区 1 。性能也可能是最好的,因为(我的直觉说)这种方法避免了至少一个字符副本。

但是,如果真的很重要,那么你应该考虑以下两点:

  • “过早优化”通常是浪费精力。 (或者换句话说,代码的这一部分的性能可能无关紧要。性能瓶颈可能在其他地方。)
  • 编写Java基准有很多陷阱,可能导致虚假的性能测量和错误的结论。

另外需要注意的是,您要做的事情(按顺序创建所有“单词”的列表)不会缩放。对于足够大的输入文件,应用程序将耗尽堆空间。如果您预计在大于100Mb左右的输入文件上运行此操作,则可能会开始成为一个问题。

解决方案可能是将您的处理转换为更基于“流”的内容......这样您就不需要在内存中包含所有单词的列表。

这与方法#1的问题基本上是同一个问题。

1 - 除非文件很小并且适合缓冲区......然后整个问题基本没有实际意义。

答案 1 :(得分:1)

如果您在实际需要时将整个文件读入内存:

  • 浪费时间:在您阅读整个文件
  • 之前,不会处理任何内容
  • 浪费空间
  • 使用不会缩放到大文件的技术。

这样做没有什么可推荐的。

答案 2 :(得分:0)

方法1:

字符串的最大大小限制,即只能使用最大长度Integer.MAX_VALUE的字符串或运行时最大的可能数组

因此,如果它是一个非常大的fie,则选择方法2