Вставка файла java с возможностью перемотки назад()/reset()

Мне нужно написать функцию, которая принимает какой-то элемент потока ввода (например, InputStream или FileChannel), чтобы прочитать большой файл за два прохода: один раз для прекомпопуляции некоторых возможностей, а второй для выполнения "реальных" " Работа. Я не хочу, чтобы весь файл загружался в память сразу (если только он не мал).

Есть ли подходящий Java-класс, который предоставляет эту возможность? FileInputStream сам по себе не поддерживает mark()/reset(). BufferedInputStream делает, я думаю, но я не знаю, нужно ли хранить весь файл для этого.

C так просто, вы просто используете fseek(), ftell() и rewind().: - (

Ответ 1

Я думаю, что ответы, ссылающиеся на FileChannel, находятся на отметке.

Здесь приведен пример реализации входного потока, который инкапсулирует эту функциональность. Он использует делегирование, поэтому он не является истинным FileInputStream, но это InputStream, которого обычно достаточно. Аналогичным образом можно расширить FileInputStream, если это требование.

Не тестируется, используйте на свой страх и риск:)

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);
    }
}

Ответ 2

BufferedInputStream поддерживает mark путем буферизации содержимого в памяти. Он лучше всего подходит для относительно небольших перспектив прогнозируемого размера.

Вместо этого RandomAccessFile можно использовать напрямую или он может служить основой для конкретного InputStream, расширенного с помощью метода rewind().

В качестве альтернативы новый FileInputStream может быть открыт для каждого прохода.

Ответ 3

Если вы получили связанный FileChannel с FileInputStream, вы можете использовать метод position для установки указателя файла в любом месте файла.

FileInputStream fis = new FileInputStream("/etc/hosts");
FileChannel     fc = fis.getChannel();


fc.position(100);// set the file pointer to byte position 100;

Ответ 4

java.nio.channels.FileChannel имеет метод position(long) to reset положение обратно к нулю, как fseek() в C.

Ответ 6

Отъезд java.io.RandomAccessFile

Ответ 7

PushbackInputStream также будет работать, если вы знаете, сколько символов вы хотите перемотать назад

Ответ 8

BufferedInputStream имеет mark(readlimit) и reset(). readlimit должен быть больше, чем filesize, чтобы сделать отметку действительной. file.length()+1 ОК. Это означает, что знак действителен до тех пор, пока не будут прочитаны readlimit байты, поэтому вы можете вернуться на reset().

Ответ 9

Вы хотите RandomAccessFileInputStream - реализовывать интерфейс InputStream с меткой /reset, иногда искать на основе RandomAccessFiles. Существуют некоторые реализации, которые могут делать то, что вам нужно.

Один пример с источниками находится в http://www.fuin.org/utils4j/index.html, но вы найдете много других, ищущих в Интернете, и его достаточно легко закодировать, если нет точно соответствует.