txt texto sobreescribir segunda por modificar linea leer escribir ejemplo como archivos archivo java file file-io

texto - ¿Cómo uso Java para leer un archivo en el que se está escribiendo activamente?



printwriter java ejemplo (9)

Estoy totalmente de acuerdo con la respuesta de Joshua , Tailer es apto para el trabajo en esta situación. Aquí hay un ejemplo :

Escribe una línea cada 150 ms en un archivo, mientras lee este mismo archivo cada 2500 ms

public class TailerTest { public static void main(String[] args) { File f = new File("/tmp/test.txt"); MyListener listener = new MyListener(); Tailer.create(f, listener, 2500); try { FileOutputStream fos = new FileOutputStream(f); int i = 0; while (i < 200) { fos.write(("test" + ++i + "/n").getBytes()); Thread.sleep(150); } fos.close(); } catch (Exception e) { e.printStackTrace(); } } private static class MyListener extends TailerListenerAdapter { @Override public void handle(String line) { System.out.println(line); } } }

Tengo una aplicación que escribe información para archivar. Esta información se utiliza después de la ejecución para determinar la aprobación / falla / corrección de la aplicación. Me gustaría poder leer el archivo mientras se está escribiendo para poder hacer estas comprobaciones de aprobación / falla / corrección en tiempo real.

Supongo que es posible hacer esto, pero ¿cuáles son los problemas involucrados al usar Java? Si la lectura se pone al día con la escritura, ¿esperará más escrituras hasta que se cierre el archivo o la lectura arrojará una excepción en este momento? Si esto último, ¿qué hago entonces?

Mi intuición actualmente me está empujando hacia BufferedStreams. ¿Es este el camino a seguir?


Hay una cola gráfica Java de código abierto que hace esto.

https://.com/a/559146/1255493

public void run() { try { while (_running) { Thread.sleep(_updateInterval); long len = _file.length(); if (len < _filePointer) { // Log must have been jibbled or deleted. this.appendMessage("Log file was reset. Restarting logging from start of file."); _filePointer = len; } else if (len > _filePointer) { // File must have had something added to it! RandomAccessFile raf = new RandomAccessFile(_file, "r"); raf.seek(_filePointer); String line = null; while ((line = raf.readLine()) != null) { this.appendLine(line); } _filePointer = raf.getFilePointer(); raf.close(); } } } catch (Exception e) { this.appendMessage("Fatal error reading log file, log tailing has stopped."); } // dispose(); }


La respuesta parece ser "no" ... y "sí". Parece que no hay una forma real de saber si un archivo está abierto para ser escrito por otra aplicación. Por lo tanto, la lectura de dicho archivo solo progresará hasta que se agote el contenido. Seguí el consejo de Mike y escribí un código de prueba:

Writer.java escribe una cadena en el archivo y luego espera a que el usuario presione enter antes de escribir otra línea en el archivo. La idea es que podría iniciarse, luego se puede iniciar un lector para ver cómo maneja el archivo "parcial". El lector que escribí está en Reader.java.

Writer.java

public class Writer extends Object { Writer () { } public static String[] strings = { "Hello World", "Goodbye World" }; public static void main(String[] args) throws java.io.IOException { java.io.PrintWriter pw = new java.io.PrintWriter(new java.io.FileOutputStream("out.txt"), true); for(String s : strings) { pw.println(s); System.in.read(); } pw.close(); } }

Reader.java

public class Reader extends Object { Reader () { } public static void main(String[] args) throws Exception { java.io.FileInputStream in = new java.io.FileInputStream("out.txt"); java.nio.channels.FileChannel fc = in.getChannel(); java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(10); while(fc.read(bb) >= 0) { bb.flip(); while(bb.hasRemaining()) { System.out.println((char)bb.get()); } bb.clear(); } System.exit(0); } }

No hay garantías de que este código sea la mejor práctica.

Esto deja la opción sugerida por Mike de verificar periódicamente si hay nuevos datos para leer del archivo. Esto requiere la intervención del usuario para cerrar el lector de archivos cuando se determina que la lectura se ha completado. O bien, el lector debe conocer el contenido del archivo y poder determinar y finalizar la condición de escritura. Si el contenido fuera XML, el final del documento podría usarse para señalar esto.


No es Java per-se, pero puede encontrar problemas en los que ha escrito algo en un archivo, pero aún no se ha escrito realmente; podría estar en un caché en alguna parte, y leer del mismo archivo puede no proporcionarle La nueva información.

Versión corta: use flush () o lo que sea la llamada al sistema relevante para garantizar que sus datos se escriban realmente en el archivo.

Tenga en cuenta que no estoy hablando de la caché de disco a nivel del sistema operativo: si sus datos entran aquí, deberían aparecer en un read () después de este punto. Puede ser que el propio lenguaje guarde en caché las escrituras, esperando hasta que un búfer se llene o el archivo se vacíe / cierre.


No puede leer un archivo que se abre desde otro proceso usando FileInputStream, FileReader o RandomAccessFile.

Pero usar FileChannel directamente funcionará:

private static byte[] readSharedFile(File file) throws IOException { byte buffer[] = new byte[(int) file.length()]; final FileChannel fc = FileChannel.open(file.toPath(), EnumSet.of(StandardOpenOption.READ)); final ByteBuffer dst = ByteBuffer.wrap(buffer); fc.read(dst); fc.close(); return buffer; }


Nunca lo he intentado, pero debe escribir un caso de prueba para ver si la lectura de una secuencia después de haber llegado al final funcionará, independientemente de si hay más datos escritos en el archivo.

¿Hay alguna razón por la que no pueda usar una secuencia de entrada / salida canalizada? ¿Los datos se escriben y leen desde la misma aplicación (si es así, tiene los datos, ¿por qué necesita leer el archivo?)

De lo contrario, tal vez lea hasta el final del archivo, luego controle los cambios y busque el lugar donde lo dejó y continúe ... aunque tenga cuidado con las condiciones de la carrera.


Si desea leer un archivo mientras se está escribiendo y solo leer el contenido nuevo, lo siguiente lo ayudará a lograr lo mismo.

Para ejecutar este programa, lo iniciará desde el símbolo del sistema / ventana de terminal y pasará el nombre del archivo a leer. Leerá el archivo a menos que elimine el programa.

Java FileReader c: / myfile.txt

A medida que escribe una línea de texto, guárdela desde el bloc de notas y verá el texto impreso en la consola.

public class FileReader { public static void main(String args[]) throws Exception { if(args.length>0){ File file = new File(args[0]); System.out.println(file.getAbsolutePath()); if(file.exists() && file.canRead()){ long fileLength = file.length(); readFile(file,0L); while(true){ if(fileLength<file.length()){ readFile(file,fileLength); fileLength=file.length(); } } } }else{ System.out.println("no file to read"); } } public static void readFile(File file,Long fileLength) throws IOException { String line = null; BufferedReader in = new BufferedReader(new java.io.FileReader(file)); in.skip(fileLength); while((line = in.readLine()) != null) { System.out.println(line); } in.close(); } }



No se pudo obtener el ejemplo para trabajar usando FileChannel.read(ByteBuffer) porque no es una lectura de bloqueo. Sin embargo, obtuve el siguiente código para que funcione:

boolean running = true; BufferedInputStream reader = new BufferedInputStream(new FileInputStream( "out.txt" ) ); public void run() { while( running ) { if( reader.available() > 0 ) { System.out.print( (char)reader.read() ); } else { try { sleep( 500 ); } catch( InterruptedException ex ) { running = false; } } } }

Por supuesto, lo mismo funcionaría como un temporizador en lugar de un hilo, pero lo dejo en manos del programador. Todavía estoy buscando una mejor manera, pero esto funciona para mí por ahora.

Ah, y voy a advertir esto con: estoy usando 1.4.2. Sí, sé que todavía estoy en la edad de piedra.