Вставка файла 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.
Ответ 5
RandomAccessFile - это то, что вы хотите:
Ответ 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, но вы найдете много других, ищущих в Интернете, и его достаточно легко закодировать, если нет точно соответствует.