具有 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:37:44  来源:igfitidea点击:

java file input with rewind()/reset() capability

javaiostream

提问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.FileChannelhas 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就是你想要的:

回答by erickson

BufferedInputStreamsupports markby buffering the content in memory. It is best reserved for relatively small look-aheads of a predictable size.

BufferedInputStreammark通过缓冲内存中的内容来支持。它最好保留用于可预测大小的相对较小的前瞻。

Instead, RandomAccessFilecan 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 FileInputStreamcan 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

BufferedInputStreamhas mark(readlimit)and reset(). readlimitshould be larger than filesizeto make mark valid. file.length()+1is OK. This means mark is valid until readlimitbytes are read, thus you can go back by reset().

BufferedInputStreammark(readlimit)reset()readlimit应该大于filesize使标记有效。 file.length()+1没问题。这意味着标记readlimit在读取字节之前一直有效,因此您可以返回reset().

回答by user1857918

What you want is RandomAccessFileInputStream- implements InputStreaminterface 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 FileChannelfrom 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;