2010-09-20 22 views
11

BinaryReader no tiene la propiedad EndOfStream. ¿Es seguro usar el siguiente código para verificar si se llega al final del flujo?EndOfStream for BinaryReader

reader.BaseStream.Length>reader.BaseStream.Position

+0

¿Qué tipo de transmisión? No todas las secuencias conocen su longitud por adelantado. –

Respuesta

7

Depende. Hay varios tipos de flujo que no implementan la propiedad Longitud o Posición, obtendría una NotSupportedException. NetworkStream por ejemplo. Por supuesto, si usa una secuencia de este tipo, realmente debe saber con anticipación la frecuencia con la que llama al método BinaryReader.Read(). Entonces, sí, está bien.

+1

Esto no es universal ... Puede haber una situación en la que necesite leer hasta el final de un NetworkStream (que sucede cuando el otro lado cierra la conexión). – torvin

+0

La expectativa es que el otro lado se despidió amablemente. Si no lo hace, la excepción que obtienes cuando continúas leyendo desde una conexión cerrada es ciertamente universal. –

-1

Eso es lo que siempre he hecho en el pasado y nunca he visto un problema con él. El código que lo usa ha estado en un entorno de producción por más de 2 años.

+5

Pruébalo en un DeflateStream en algún momento. . . –

+0

¿Y con qué tipo de transmisión? –

+0

@Jim No lo sabía. Esa es una buena información, gracias. La respuesta de Henk obtiene un +1 entonces. –

2

Esto no funcionará como una solución general porque asume que el valor BaseStream admite la propiedad Length. La implementación de muchos Stream no lo hace y en su lugar arrojar un NotSupportedException. En particular, cualquier flujo base de red como HttpRequestStream y NetworkStream

10

La manera más fácil que encontré es verificar el valor devuelto del método PeekChar() del BinaryReader. Si devuelve -1, llegaste al final de la transmisión.

+1

Esto funciona a menos que el flujo subyacente no sea compatible con la búsqueda. –

+0

Sí, también descubrí que en la práctica, si llamas 'PeekChar()' a menudo, puede ser extremadamente lento cuando se trata de archivos. –

+0

Además, parece arrojar una excepción si los datos en esa posición resultan ser un carácter no válido. A veces obtengo esto: 'System.ArgumentException: el buffer de salida de char es demasiado pequeño para contener los caracteres decodificados, codificando 'Unicode (UTF-8)' de nuevo 'System.Text.DecoderReplacementFallback''. –

1

Me he dado cuenta de que la comparación de la posición con la longitud NO funciona en StreamReader, incluso si el BaseStream subyacente admite la búsqueda. Parece que StreamReader almacena la lectura anticipada de BaseStream. Este debe ser el motivo por el que StreamReader proporciona una propiedad EndOfStream, lo cual es algo bueno, y desearía que BinaryReader hiciera lo mismo.

Comprobación de estos valores (longitud y posición) sobre los recuentos de subyacentes flujo base en BinaryReader a no comportarse como lo hace StreamReader, es decir, se basa en BinaryReader solamente agarrando el número exacto de bytes de BaseStream necesario para cumplir con una llamada de método usuario. Es de suponer que si BinaryReader funciona de esta manera internamente, es por eso que no necesita suministrar un EndOfStream, pero ciertamente desearía que fuera uno para que supiera que el final del archivo se manejaba correctamente para los clientes de una manera independiente de la implementación.

Por supuesto, los lectores no son flujos, pero con respecto al comportamiento del final del archivo sería bueno si hubiera una interfaz común que permitiera a los clientes de clases de entrada/salida saber si A. fin de archivo es un concepto sensato para la fuente de datos subyacente, y B. cuando finaliza el archivo si A es sensato.

0

Compruebe la propiedad Streams CanSeek. Si esta propiedad devuelve verdadero, puede comparar la Longitud de las secuencias con la Posición de la secuencia para saber si se encuentra al final de la secuencia. Si esta propiedad devuelve falso, esto no funcionará.

Para las transmisiones de red puede necesitar distinguir entre el final de los bytes disponibles (el cliente en el otro extremo tiene aún más por escribir pero aún no) y la secuencia se está cerrando. La propiedad IsConnected para una conexión Tcp subyacente no es confiable para saber cuándo se cerró la transmisión. Es posible enumerar las conexiones que tiene la computadora y ver si la transmisión que está utilizando está entre ellas. Esto es más confiable, pero más complejo. Puede ser mejor manejar IOExceptions cuando no puede leer