Java 从文件中读取特定行的速度非常慢
我创建了一个方法,可以根据文件的行号从文件中读取特定的行。它适用于大多数文件,但当我试图读取一个包含大量非常长的行的文件时,它需要很长时间,尤其是当它在文件中的位置越来越低时。我也做了一些调试,看起来也占用了很多内存,但我不确定这是否是可以改进的。我知道还有一些其他问题是关于如何从文件中读取某些行的,但这个问题主要集中在性能方面Java 从文件中读取特定行的速度非常慢,java,performance,file,Java,Performance,File,我创建了一个方法,可以根据文件的行号从文件中读取特定的行。它适用于大多数文件,但当我试图读取一个包含大量非常长的行的文件时,它需要很长时间,尤其是当它在文件中的位置越来越低时。我也做了一些调试,看起来也占用了很多内存,但我不确定这是否是可以改进的。我知道还有一些其他问题是关于如何从文件中读取某些行的,但这个问题主要集中在性能方面 public static final synchronized List<String> readLines(final File file, final
public static final synchronized List<String> readLines(final File file, final Integer start, final Integer end) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
List<String> lines = new ArrayList<>();
try {
String line = bufferedReader.readLine();
Integer currentLine = 1;
while (line != null) {
if ((currentLine >= start) && (currentLine <= end)) {
lines.add(line + "\n");
}
currentLine++;
if (currentLine > end) {
return lines;
}
line = bufferedReader.readLine();
}
} finally {
bufferedReader.close();
}
return lines;
}
public static final synchronized List readLines(最终文件文件、最终整数开始、最终整数结束)引发IOException{
BufferedReader BufferedReader=新的BufferedReader(新文件读取器(文件));
列表行=新的ArrayList();
试一试{
String line=bufferedReader.readLine();
整数currentLine=1;
while(行!=null){
如果((当前线路>=开始)&&(当前线路结束){
回流线;
}
line=bufferedReader.readLine();
}
}最后{
bufferedReader.close();
}
回流线;
}
如何优化此方法,使其比光速更快?我意识到,我以前所做的工作天生就很慢,而且占用了太多内存 通过将所有行添加到内存中,然后处理
列表中的所有行,这不仅花费了两倍的时间,而且还无缘无故地创建了字符串
变量
我现在正在使用Java8Stream
并在阅读时进行处理,这是我迄今为止使用的最快的方法
Path path = Paths.get(file.getAbsolutePath());
Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8);
for (String line : (Iterable<String>) stream::iterator) {
//do stuff
}
}
Path Path=Path.get(file.getAbsolutePath());
Stream=Files.lines(路径,StandardCharsets.UTF_8);
for(字符串行:(Iterable)流::迭代器){
//做事
}
}
我意识到我以前做的事情天生就很慢,而且占用了太多内存
通过将所有行添加到内存中,然后处理列表中的所有行,这不仅花费了两倍的时间,而且还无缘无故地创建了字符串
变量
我现在正在使用Java8Stream
并在阅读时进行处理,这是我迄今为止使用的最快的方法
Path path = Paths.get(file.getAbsolutePath());
Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8);
for (String line : (Iterable<String>) stream::iterator) {
//do stuff
}
}
Path Path=Path.get(file.getAbsolutePath());
Stream=Files.lines(路径,StandardCharsets.UTF_8);
for(字符串行:(Iterable)流::迭代器){
//做事
}
}
尝试使用类似.limit(end-start)
和.collect(Collectors.toList())的方法
。您可能可以搜索开始
行,然后只读取结束-开始
行您可以进行的一个小优化的可能副本是增加缓冲读取器的大小
,以便它在内存中保存更多数据。例如,使用新的缓冲读取器(文件,128*1024)
而不是默认值。@Hooli,类似这样的东西(注意:未测试的代码)列出行=文件。行(path.get(“yourfile.txt”)。跳过(start)。限制(end-start)。收集(Collectors.toList());
。但我怀疑它会比您已有的解决方案快得多。请尝试使用类似.limit(end-start)的东西
和.collect(Collectors.toList())
。您可能可以搜索开始
行,然后只读取结束-开始
行您可以进行的一个小优化的可能副本是增加缓冲读取器的大小
,以便它在内存中保存更多数据。例如,使用新的缓冲读取器(文件,128*1024)
而不是默认值。@Hooli,类似这样的内容(注意:未测试的代码)列出行=文件。行(路径。get(“yourfile.txt”)。跳过(开始)。限制(结束-开始)。收集(收集器。toList());
。但我怀疑它是否会比您已有的解决方案快得多。这与您在原始示例中所做的没有本质上的区别。因此可能会发生其他情况。与其猜测问题所在,不如尝试分析它使用visualvm甚至jtop实际花费时间的位置。您的code看起来不错,我认为它性能不佳的唯一原因是,如果堆太小,它就会开始垃圾收集。而且,synchronized是可疑的,你有很多方法从多个线程调用它吗?@JillesvanGurp:我也这么认为,关于synchronized
,但去掉它之后,没有注意到di区别。没有线程,我只是认为在实用方法上使用它是一个很好的实践。分析这种方法有点困难,因为所有重要的位都发生在幕后,在jvm代码中。这与您在原始示例中所做的没有本质上的区别。所以可能会发生其他事情。老鼠与其猜测问题是什么,不如试着分析一下它使用visualvm甚至jtop实际花费时间的位置。你的代码看起来不错,我认为它性能不佳的唯一原因是,如果堆太小,它会开始垃圾收集。而且synchronized是可疑的,你有很多方法调用t吗他从多线程中得到的东西?@JillesvanGurp:我对同步的也有同样的想法,但取出后没有发现任何区别。没有线程,我只是认为将其用于实用方法是一种很好的做法。分析这种方法有点困难,因为所有重要的部分都发生在幕后,在jvm代码中。