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();
}
回流线;
}

如何优化此方法,使其比光速更快?

我意识到,我以前所做的工作天生就很慢,而且占用了太多内存

通过将所有行添加到内存中,然后处理
列表中的所有行,这不仅花费了两倍的时间,而且还无缘无故地创建了
字符串
变量

我现在正在使用Java8
Stream
并在阅读时进行处理,这是我迄今为止使用的最快的方法

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)流::迭代器){
//做事
}   
}

我意识到我以前做的事情天生就很慢,而且占用了太多内存

通过将所有行添加到内存中,然后处理
列表中的所有行,这不仅花费了两倍的时间,而且还无缘无故地创建了
字符串
变量

我现在正在使用Java8
Stream
并在阅读时进行处理,这是我迄今为止使用的最快的方法

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代码中。