具有 rewind()/reset() 功能的 java 文件输入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1094703/
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 file input with rewind()/reset() capability
提问by Jason S
I need to write a function that takes in some kind of input stream thing (e.g. an InputStream or a FileChannel) in order to read a large file in two passes: once to precompute some capacities, and second to do the "real" work. I do not want the whole file loaded into memory at once (unless it is small).
我需要编写一个接受某种输入流事物(例如 InputStream 或 FileChannel)的函数,以便分两次读取大文件:一次是预先计算一些容量,第二次是做“真正的”工作。我不希望将整个文件一次加载到内存中(除非它很小)。
Is there an appropriate Java class that provides this capability?FileInputStream itself does not support mark()/reset(). BufferedInputStream does, I think, but I'm not clear whether it has to store the whole file to do this.
是否有提供此功能的适当 Java 类?FileInputStream 本身不支持 mark()/reset()。BufferedInputStream 确实如此,我认为,但我不清楚它是否必须存储整个文件才能做到这一点。
C is so simple, you just use fseek(), ftell(), and rewind(). :-(
C 非常简单,您只需使用 fseek()、ftell() 和 rewind()。:-(
采纳答案by ykaganovich
I think the answers referencing a FileChannel are on the mark .
我认为引用 FileChannel 的答案是正确的。
Here's a sample implementation of an input stream that encapsulates this functionality. It uses delegation, so it's not a true FileInputStream, but it is an InputStream, which is usually sufficient. One could similarly extend FileInputStream if that's a requirement.
这是封装此功能的输入流的示例实现。它使用委托,所以它不是一个真正的 FileInputStream,而是一个 InputStream,这通常就足够了。如果需要,可以类似地扩展 FileInputStream。
Not tested, use at your own risk :)
未经测试,使用风险自负:)
public class MarkableFileInputStream extends FilterInputStream {
private FileChannel myFileChannel;
private long mark = -1;
public MarkableFileInputStream(FileInputStream fis) {
super(fis);
myFileChannel = fis.getChannel();
}
@Override
public boolean markSupported() {
return true;
}
@Override
public synchronized void mark(int readlimit) {
try {
mark = myFileChannel.position();
} catch (IOException ex) {
mark = -1;
}
}
@Override
public synchronized void reset() throws IOException {
if (mark == -1) {
throw new IOException("not marked");
}
myFileChannel.position(mark);
}
}
回答by Rich Seller
Check out java.io.RandomAccessFile
查看 java.io.RandomAccessFile
回答by Arne Burmeister
java.nio.channels.FileChannel
has a method position(long)
to reset the position back to zero like fseek() in C.
java.nio.channels.FileChannel
有一种方法position(long)
可以像 C 中的 fseek() 一样将位置重置为零。
回答by dfa
RandomAccessFileis what you want:
RandomAccessFile就是你想要的:
- fseek() is translated to RandomAccessFile#seek
- ftell() is translated to RandomAccessFile#getFilePointer
- rewind() is seek(0)
- fseek() 被转换为RandomAccessFile#seek
- ftell() 被转换为RandomAccessFile#getFilePointer
- 倒带()是寻求(0)
回答by erickson
BufferedInputStream
supports mark
by buffering the content in memory. It is best reserved for relatively small look-aheads of a predictable size.
BufferedInputStream
mark
通过缓冲内存中的内容来支持。它最好保留用于可预测大小的相对较小的前瞻。
Instead, RandomAccessFile
can be used directly, or it could serve as the basis for a concrete InputStream
, extended with a rewind()
method.
相反,RandomAccessFile
可以直接使用,也可以作为具体的基础InputStream
,用rewind()
方法进行扩展。
Alternatively, a new FileInputStream
can be opened for each pass.
或者,FileInputStream
可以为每个通行证打开一个新的。
回答by CT Arrington
PushbackInputStream will also work, as long as you know how many characters you want to be able to rewind
PushbackInputStream 也可以使用,只要您知道想要倒带多少个字符
回答by Byung Ahn
BufferedInputStream
has mark(readlimit)
and reset()
.
readlimit
should be larger than filesize
to make mark valid.
file.length()+1
is OK.
This means mark is valid until readlimit
bytes are read, thus you can go back by reset()
.
BufferedInputStream
有mark(readlimit)
和reset()
。
readlimit
应该大于filesize
使标记有效。
file.length()+1
没问题。这意味着标记readlimit
在读取字节之前一直有效,因此您可以返回reset()
.
回答by user1857918
What you want is RandomAccessFileInputStream
- implements InputStream
interface with mark/reset, sometimes seek based on RandomAccessFiles
. Some implementations exist which might do what you need.
你想要的是RandomAccessFileInputStream
- 实现InputStream
带有标记/重置的接口,有时基于RandomAccessFiles
. 存在一些可能满足您需求的实现。
One example complete with sources is in http://www.fuin.org/utils4j/index.htmlbut you would find many others searching the internet and its is easy enough to code if none fits exactly.
一个完整的示例在http://www.fuin.org/utils4j/index.html 中,但您会发现许多其他人在互联网上搜索,如果没有一个完全适合,它很容易编码。
回答by SW-Eng
If you get the associated FileChannel
from the FileInputStream
, you can use the position method to set the file pointer to anywhere in the file.
如果FileChannel
从 中获取关联,则FileInputStream
可以使用 position 方法将文件指针设置为文件中的任何位置。
FileInputStream fis = new FileInputStream("/etc/hosts");
FileChannel fc = fis.getChannel();
fc.position(100);// set the file pointer to byte position 100;