2010-09-09 14 views
5

Tengo un programa Writer que escribe una línea de texto en un archivo, luego espera hasta que el usuario toque return antes de escribir otra línea y luego salir. Solo después de eso se cierra el archivo. El código:¿Por qué FileInputStream read() no bloquea?

public class Writer { 

    Writer() { 
    } 

    public static String[] strings = 
     { 
      "Hello World", 
      "Goodbye World" 
     }; 

    public static void main(String[] args) 
     throws java.io.IOException { 

     java.io.FileOutputStream pw = 
      new java.io.FileOutputStream("myfile.txt"); 

     for(String s : strings) { 
      pw.write(s.getBytes()); 
      System.in.read(); 
     } 

     pw.close(); 
    } 
} 

de inicio por primera vez con:

java escritor

Entonces también tengo un programa lector que debería (así lo esperaba) bloquean el tiempo que la redacción de la el archivo no ha terminado aún (es decir, pw.close() aún no se ha llamado). El código:

public class ReaderFIS extends Object { 

    ReaderFIS() { 
    } 

    public static void main(String[] args) throws Exception { 

     java.io.FileInputStream in = new java.io.FileInputStream("myfile.txt"); 

     int ch = -1; 
     while((ch = in.read()) >= 0) { 
     System.out.println("ch = " + ch); 
    } 
     System.out.println("Last ch = " + ch); 

    System.out.println("exiting"); 
    } 
} 

Inicio con:

ReaderFIS java

Ahora que esperaba la lectura() para bloquear después de leer el primer texto "Hello World", en base a esto en la documentación de Javadoc:

Lee un byte de datos de esta secuencia de entrada. Este método bloquea si aún no hay entradas disponibles. Vía: http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read()

Pero el ReaderFIS se realiza inmediatamente después de leer "Hello World" y aparentemente ve un EOF! ¡Así que hace no el bloque! Vacia los valores de caracteres, luego a -1 y luego imprime "salir".

de salida: ch = 72 ch = 101 ch = 108 ch = 108 ch = 111 ch = 32 ch = 87 ch = 111 ch = 114 ch = 108 ch = 100 Última ch = -1 salir

Otras variaciones que probamos eran: la lectura a través de un getChannel(), el control a través de getChannel() si puede ser de bloqueo() ed, utilizando disponible(), intentando leer() usando una buffer, intentando readLine(), escribiendo continuamente un char Acceda al archivo con una pausa de 500 ms entre cada escritura, sin escribir nada, solo manteniendo el archivo abierto en Writer.
Ninguna de estas variaciones hace que el programa ReaderFIS se bloquee, siempre termina.

¿Por qué el programa lector no bloquea? ¿Extrañé algo tan tan obvio? Parece que el programa ReaderFIS encuentra un EOF (-1), pero ¿por qué? El programa no ha sido cerrado aún por el programa Writer.

Nota al margen "graciosa": el System.in.read() está bloqueando. (y esperando que el usuario presione Enter).

PD: intenté esto en Windows XP y Suse Linux. En Windows no puedo borrar el archivo mientras el escritor se está ejecutando (que es como esperaba).

Saludos, Marco

+0

cuando escribe en disco, fuerza un EOF, ¿no? el EOF solo se mueve al agregar información nueva. Pero el bloque en el disco tiene que tener un EOF ... – jcolebrand

+0

Así que está diciendo que el EOF está * siempre * escrito porque un archivo siempre necesita uno. Pero pensé que un EOF solo se escribe al final después de enjuagar y cerrar el archivo. Pero eso significa que mi lectura() nunca se bloqueará cuando lea un archivo porque siempre hay * un * EOF y siempre devuelve un -1 incluso si el archivo está vacío. Entonces, ¿el JavaDoc es incorrecto? – QQQuestions

Respuesta

0

que poco no alcanzó lo que está bloqueando. El bloqueo de IO es uno que bloquea la ejecución del programa hasta que termina la operación IO. close simplemente desconecte el programa del archivo. Si quieres que una aplicación bloquee a otra debes usar algún tipo de sincronización.

+0

Realmente no entiendo lo que estás diciendo aquí. – QQQuestions

+0

@qqquestions ok. Esta suposición: "Entonces también tengo un programa lector que debería (así lo esperaba) bloquear mientras la escritura del archivo no haya terminado aún (es decir, pw.close() aún no se ha llamado)." es completamente incorrecto El lector/escritor no se bloquea entre sí. (Solo en caso de que intente leer/escribir solo archivo simultáneamente, pero no es el caso aquí). google "non blocking io in java", encontrarás artículos que explican mi respuesta en detalle. – Andrey

+0

¿Por qué dices que mis 2 programas no se leen/escriben el mismo archivo individual simultáneamente? ¿O te refieres a * exactamente * al mismo tiempo?Busqué en Google sus palabras clave sugeridas, pero eso no me brindó ninguna información nueva, solo éxitos que expliquen qué IO sin bloqueo es. ¿Estás diciendo que mi escritor y lector no bloquean? Pero ¿por qué JavaDoc dice que read() debería estar bloqueando ("Este método bloquea si todavía no hay entradas disponibles") y cómo puede incluso leer el archivo mientras todavía no tiene EOF escrito? Y yo * quiero * que mi lectura() bloquee, como dice el documento Java, no quiero IO sin bloqueo. – QQQuestions

1

Su programa de lectura solo leerá lo que esté en el archivo, luego presione el final y devuelva -1. Si todo lo que contiene en el momento en que lo ejecuta es "Hello World", eso es todo lo que podrá leer. Si lo ejecuta de nuevo después de presionar Intro en su escritor, debería ver "Hello World Goodbye World".

Tener no más bytes disponibles y tocar el final de una secuencia son dos cosas diferentes. Es por eso que los bloques System.in.read() y FileInputStream.read() no lo hacen.

+0

¿Estás diciendo que mi lectura() está al final de la transmisión? ¿Por qué sería? El escritor todavía está allí y tiene el archivo/secuencia abierta. ¿Y qué sería un ejemplo cuando el FileInputStream.read() bloqueará? El código de ejemplo sería genial ... – QQQuestions

+0

Eso es exactamente lo que estoy diciendo. No puedo imaginar que FileInputStream.read() bloqueará alguna vez durante un período de tiempo significativo para leer un archivo local. El bloqueo es algo que generalmente ocurrirá en otros tipos de InputStreams que son abstracciones de cosas con mayor latencia (lecturas de socket, etc.). – Seth

+0

¿Entonces el Javadoc es incorrecto? Dice que bloqueará para FileInputStreams. – QQQuestions

1

FileInputStream siempre tiene entrada disponible: o bien quedan bytes por leer o hay un EOF, pero en general no se bloqueará al leer. Puede bloquearse cuando vaya a:

  • lectura desde una consola/terminal de
  • lectura de la red
  • lectura de un tubo de
  • lectura de lo corriente que es de espera para los datos. Secuencias

de archivos no tienen que esperar los datos, ya que siempre tienen datos disponibles: en su caso read() conseguirá, básicamente, al azar, uno de:

  • la versión anterior del archivo
  • la nueva versión del archivo
  • versión medio actualizada del archivo.
+0

Entonces, también está implicando que el Javadoc es incorrecto, * File * InputStreams nunca bloqueará en una lectura? – QQQuestions

+1

No, javadoc dice que InputStreams bloqueará * si los datos de entrada no están disponibles *. Lo que estoy diciendo es que FileInputStreams siempre tiene entrada disponible, por lo que, de acuerdo con javadoc, no es necesario que bloqueen. Técnicamente, aún podrían bloquear en algunos casos de esquina, como leer un archivo con un 'FileLock', pero ese no parece ser el caso. – gpeche

+0

Llámame exigente, pero entonces los documentos deberían haber dicho eso, ahora se puede leer (por mí :) ya que siempre está bloqueando si aún no hay entradas disponibles. Me sorprende que vea un EOF antes de que se cierre el archivo, pero aparentemente (según el primer comentario de mi publicación original), siempre habrá un EOF y ese siempre se puede leer. – QQQuestions

0

No puede usar archivos como tuberías.

Sin embargo, puede utilizar tubos como tuberías.

+0

Sí, supongo que el comportamiento que estoy buscando es el comportamiento de la tubería. Pero mi pregunta es por qué no bloquea, mientras que el Javadoc dice que bloquea ... – QQQuestions

+0

¿Lo tiene? ¿Dónde dice eso? – EJP

+0

Ver mi publicación inicial: Lee un byte de datos de esta corriente de entrada. Este método bloquea si aún no hay entradas disponibles. Vía: http://download-llnw.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#read%28%29 – QQQuestions

Cuestiones relacionadas