sobreescribir - entrada de archivo java con capacidad de rebobinar()/restablecer()
printwriter java ejemplo (9)
Consulte java.io.RandomAccessFile
Necesito escribir una función que tome algún tipo de flujo de entrada (por ejemplo, un InputStream o un FileChannel) para leer un archivo grande en dos pasos: una para precalcular algunas capacidades y la segunda para hacer el trabajo "real". No quiero que todo el archivo se cargue en la memoria a la vez (a menos que sea pequeño).
¿Hay una clase Java adecuada que proporcione esta capacidad? FileInputStream en sí mismo no es compatible con mark () / reset (). BufferedInputStream sí, creo, pero no estoy seguro de si tiene que almacenar todo el archivo para hacer esto.
C es tan simple que solo usas fseek (), ftell () y rewind (). :-(
Creo que las respuestas que hacen referencia a un FileChannel están en la marca.
Aquí hay una implementación de muestra de una secuencia de entrada que encapsula esta funcionalidad. Utiliza la delegación, por lo que no es un verdadero FileInputStream, pero es un InputStream, que por lo general es suficiente. Uno podría extender FileInputStream de manera similar si eso es un requisito.
No probado, use bajo su propio riesgo :)
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);
}
}
Lo que quiere es RandomAccessFileInputStream
: implementa la interfaz InputStream
con mark / reset, a veces busca basado en RandomAccessFiles
. Existen algunas implementaciones que pueden hacer lo que necesita.
Un ejemplo completo con las fuentes se encuentra en http://www.fuin.org/utils4j/index.html pero encontrará muchos otros que buscan en Internet y es bastante fácil de codificar si ninguno encaja exactamente.
PushbackInputStream también funcionará, siempre que sepa cuántos caracteres desea rebobinar
Si obtiene el FileChannel
asociado de FileInputStream
, puede usar el método de posición para establecer el puntero del archivo en cualquier parte del archivo.
FileInputStream fis = new FileInputStream("/etc/hosts");
FileChannel fc = fis.getChannel();
fc.position(100);// set the file pointer to byte position 100;
RandomAccessFile es lo que quieres:
- fseek () se traduce a RandomAccessFile#seek
- ftell () se traduce a RandomAccessFile#getFilePointer
- rebobinar () es buscar (0)
BufferedInputStream
admite mark
al almacenar el contenido en la memoria. Es mejor reservarlo para look-aheads relativamente pequeños de un tamaño predecible.
En cambio, RandomAccessFile
se puede usar directamente, o podría servir como base para un InputStream
concreto, extendido con un método de rewind()
.
Alternativamente, se puede abrir un nuevo FileInputStream
para cada pase.
BufferedInputStream
tiene mark(readlimit)
y reset()
. readlimit
debe ser mayor que el filesize
de filesize
para que la marca sea válida. file.length()+1
está bien. Esto significa que la marca es válida hasta que se readlimit
bytes de readlimit
, por lo que puede volver por reset()
.
java.nio.channels.FileChannel
tiene una position(long)
método position(long)
para restablecer la posición a cero como fseek () en C.