我正在尝试从文本文件中读取特定行,但是我不想将文件加载到内存中(它可能变得非常大)。
我一直在寻找,但我发现的每个例子都要求读取每一行(这会减慢我的代码,因为有超过100,000行)或者将整个事物加载到一个数组中并获得正确的元素(文件将具有很多行输入)。
我想做的一个例子:
String line = File.getLine(5);
“代码不是实际代码,它是为了显示我想要的原则”
有办法做到这一点吗?
- - - - - - - - 编辑
我刚刚意识到这个文件也会在读取行之间写入(添加到文件的末尾)。
答案 0 :(得分:12)
有办法做到这一点吗?
除非每行都有固定的字节数,否则不是。
你不必实际保持内存中的每一行 - 但是你必须通读整个文件才能到达你想要的那一行,否则你将不知道在哪里开始阅读。
答案 1 :(得分:3)
您必须逐行读取文件。否则你怎么知道什么时候你到了第5行(如你的例子)?
编辑:
您可能还想查看Random Access Files,如果您知道每行有多少字节,这可能会有所帮助,正如Jon Skeet所说。
答案 2 :(得分:3)
最简单的方法是使用BufferedReader(http://docs.oracle.com/javase/1.5.0/docs/api/java/io/BufferedReader.html),因为您可以指定缓冲区大小。你可以这样做:
BufferedReader in = new BufferedReader(new FileReader(“foo.in”),1024);
in.readLine();
in.readLine();
in.readLine();
in.readLine();
String line = in.readLine();
答案 3 :(得分:2)
1)读取用户选择的行
如果您只需要一次或不经常读取用户选择的行(或者文件足够小),那么您只需要从头开始逐行读取文件,直到您进入选定行线。
另一方面,如果需要经常读取用户选择的行,则应构建行号和偏移量的索引。因此,例如,第42行对应于文件中2347字节的偏移量。理想情况下,您只需读取整个文件一次并存储索引 - 例如,在地图中,使用行号作为键和偏移作为值。
2)读取自之后添加的新行 最后一次阅读。我计划每10秒读取一次文件。我有 行数,可以找到新的行号,但我需要 读那行
对于第二点,您可以简单地将当前偏移量保存到文件中,而不是保存当前行号 - 但如果它继续提供显着的性能优势,那么继续构建索引肯定不会受到影响。
但是,除非性能已经成为问题或极有可能成为问题,否则不要过度使用性能优化。
答案 4 :(得分:0)
执行此操作的唯一方法是构建每行所在位置的索引(您只需要记录每行的结尾)如果没有从一开始就基于索引随机访问行的方法,您必须读取该行之前的每个字节。
BTW:在快速机器上读取100,000行可能只需要一秒钟。
答案 5 :(得分:0)
如果性能是一个很大的问题,并且你经常从静态文件中读取随机行,那么你可以通过读取文件并构建一个索引(基本上只是long[]
)来优化这一点。文件每一行的偏移量。
一旦你有了这个,你就知道在文件中准确跳转到哪里,然后你可以读到下一个换行符来检索整行。
答案 6 :(得分:0)
以下是我所拥有的一些代码片段,它将读取文件并将每第10行写入包括第一行到新文件(编写器)。您可以随时将try部分替换为您想要执行的任何操作。要更改要读取的行数,只需更改if语句中的0" lc.endsWith(" 0")"到你想读的任何一行。但是如果在读取文件时正在写入文件,则此代码仅在您运行此代码时才能使用文件中包含的数据。
LineNumberReader lnr = new LineNumberReader(new FileReader(new File(file)));
lnr.skip(Long.MAX_VALUE);
int linecount=lnr.getLineNumber();
lnr.close();
for (int i=0; i<=linecount; i++){
//read lines
String line = bufferedReader.readLine();
String lc = String.valueOf(i);
if (lc.endsWith("0")){
try{
writer.append(line+"\n");
writer.flush();
}catch(Exception ee){
}
}
}
答案 7 :(得分:0)
对于小文件:
String line = Files.readAllLines(Paths.get("file.txt")).get(n);
对于大文件:
String line;
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
line = lines.skip(n).findFirst().get();
}
Java 7:
String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
for (int i = 0; i < n; i++)
br.readLine();
line = br.readLine();
}