Java BufferedReader 回到文本文件的顶部?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/262618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java BufferedReader back to the top of a text file?
提问by
I currently have 2 BufferedReader
s initialized on the same text file. When I'm done reading the text file with the first BufferedReader
, I use the second one to make another pass through the file from the top. Multiple passes through the same file are necessary.
我目前BufferedReader
在同一个文本文件上初始化了2秒。当我用第一个 阅读完文本文件时BufferedReader
,我使用第二个从顶部再次通过文件。需要多次通过同一个文件。
I know about reset()
, but it needs to be preceded with calling mark()
and mark()
needs to know the size of the file, something I don't think I should have to bother with.
我知道reset()
,但它需要在调用之前mark()
并mark()
需要知道文件的大小,我认为我不应该打扰。
Ideas? Packages? Libs? Code?
想法?包裹?图书馆?代码?
Thanks TJ
谢谢 TJ
采纳答案by Jon Skeet
What's the disadvantage of just creating a new BufferedReader
to read from the top? I'd expect the operating system to cache the file if it's small enough.
只是创建一个新的BufferedReader
从顶部读取的缺点是什么?如果文件足够小,我希望操作系统缓存文件。
If you're concerned about performance, have you proved it to be a bottleneck? I'd just do the simplest thing and not worry about it until you have a specific reason to. I mean, you could just read the whole thing into memory and then do the two passes on the result, but again that's going to be more complicated than just reading from the start again with a new reader.
如果您担心性能,您是否证明它是一个瓶颈?我只会做最简单的事情,除非你有特定的理由,否则我不会担心。我的意思是,您可以将整个内容读入内存,然后对结果进行两次传递,但这又比仅使用新阅读器从头开始读取要复杂得多。
回答by Ryan P
The Buffered readers are meant to read a file sequentially. What you are looking for is the java.io.RandomAccessFile, and then you can use seek()
to take you to where you want in the file.
缓冲读取器旨在按顺序读取文件。您正在寻找的是java.io.RandomAccessFile,然后您可以使用它seek()
来将您带到文件中所需的位置。
The random access reader is implemented like so:
随机访问阅读器的实现如下:
try{
String fileName = "c:/myraffile.txt";
File file = new File(fileName);
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.readChar();
raf.seek(0);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The "rw"
is a mode character which is detailed here.
The reason the sequential access readers are setup like this is so that they can implement their buffers and that things can not be changed beneath their feet. For example the file reader that is given to the buffered reader should only be operated on by that buffered reader. If there was another location that could affect it you could have inconsistent operation as one reader advanced its position in the file reader while the other wanted it to remain the same now you use the other reader and it is in an undetermined location.
顺序访问读取器设置成这样的原因是为了它们可以实现缓冲区,并且不能在它们脚下进行更改。例如,提供给缓冲读取器的文件读取器只能由该缓冲读取器操作。如果有另一个可能影响它的位置,您可能会出现不一致的操作,因为一个读取器将其在文件读取器中的位置提前,而另一个则希望它保持不变,现在您使用另一个读取器并且它位于未确定的位置。
回答by Davide
The best way to proceed is to change your algorithm, in a way in which you will NOT need the second pass. I used this approach a couple of times, when I had to deal with huge (but not terrible, i.e. few GBs) files which didn't fit the available memory.
最好的方法是改变你的算法,这样你就不需要第二遍了。当我不得不处理不适合可用内存的巨大(但并不可怕,即几 GB)文件时,我多次使用这种方法。
It might be hard, but the performance gain usually worths the effort
这可能很难,但性能提升通常值得付出努力
回答by anjanb
"The whole business about mark() and reset() in BufferedReader smacks of poor design."
“在 BufferedReader 中关于 mark() 和 reset() 的整个业务都带有糟糕的设计味道。”
why don't you extend this class and have it do a mark() in the constructor() and then do a seek(0) in topOfFile() method.
为什么不扩展这个类并让它在构造函数()中做一个标记(),然后在 topOfFile()方法中做一个搜索(0)。
BR,
~A
BR,
~A
回答by Zarkonnen
About mark/reset:
关于标记/重置:
The mark method in BufferedReader takes a readAheadLimit parameter which limits how far you can read after a mark before reset becomes impossible. Resetting doesn't actually mean a file system seek(0), it just seeks inside the buffer. To quote the Javadoc:
BufferedReader 中的 mark 方法采用 readAheadLimit 参数,该参数限制了在重置变得不可能之前的标记后您可以读取的距离。重置实际上并不意味着文件系统搜索(0),它只是在缓冲区内搜索。引用 Javadoc:
readAheadLimit - Limit on the number of characters that may be read while still preserving the mark. After reading this many characters, attempting to reset the stream may fail. A limit value larger than the size of the input buffer will cause a new buffer to be allocated whose size is no smaller than limit. Therefore large values should be used with care.
readAheadLimit - 限制在保留标记的同时可以读取的字符数。读取这么多字符后,尝试重置流可能会失败。大于输入缓冲区大小的限制值将导致分配大小不小于限制的新缓冲区。因此,应谨慎使用较大的值。