2010-06-03 27 views

Respuesta

5

No haría eso, lo dejaría en el nivel de abstracción más alto posible. Si no va a utilizar las capacidades de marca y reinicio de un BufferedStream, ¿por qué molestarse en envolverlo?

Si un consumidor lo necesita, es mejor envolverlo allí.

+5

Esto parece implicar que la marca y el restablecimiento son las únicas cosas útiles que 'BufferedInputStream' agrega sobre un' InputStream' simple. Esto podría ser cierto desde un sentido de API, pero como otros han dicho, 'BufferedInputStream' se ocupa de las lecturas de almacenamiento intermedio para usted. Leer byte a tiempo desde un 'FileInputStream' desnudo es 40 veces más lento que leer uno envuelto en un' BufferedInputStream'. Dicho esto, devuelve el 'InputStream' y conserva la firma de tu método como tal. Los usuarios pueden envolver si así lo desean. – jasonmp85

+0

Acepto que, desde el punto de vista del rendimiento, es mejor envolverlo en el 99,9% de los casos. Sin embargo, alivia al consumidor de su responsabilidad de pensar cómo usar el InputStream. Este tipo de suposiciones del consumidor limita la reutilización. –

+0

Creo que en más de un 0.1% de los casos, el consumidor no leerá un byte a la vez y en su lugar usará algún tipo de búfer, en cuyo caso el BufferedInputStream es inútil. –

0

También depende de cómo va a leer desde el InputStream. Si vas a leer un carácter/byte a la vez (es decir, leer()), entonces BufferedInputStream reducirá tus gastos generales haciendo lecturas en bloque en tu nombre. Si vas a leerlo en un array de 4k u 8k byte/char un bloque a la vez, es probable que BuffredInputStream no te beneficie.

25

¿Tiene sentido que siempre envolver un InputStream como BufferedInputStream, cuando sé si el InputStream dado es algo que no sea amortiguada?

Tiene sentido si son propensos a realizar una gran cantidad de pequeñas lecturas (un byte o unos pocos bytes a la vez), o si desea utilizar algunas de las funciones de nivel superior que ofrece por las API almacenadas; por ejemplo, el método BufferedReader.readLine().

Sin embargo, si sólo se va a realizar la gran bloque lee utilizando los métodos read(byte[]) y/o read(byte[], int, int), envolviendo el InputStream en un BufferedInputStream no ayuda.

(En respuesta al comentario de @Peter Tillman en su propia respuesta, el bloque de leer casos de uso sin duda representan más del 0,1% de los usos de InputStream clases !! Sin embargo, él es correcta en el sentido de que por lo general es inofensiva para usar un API con búfer cuando no es necesario)

2

Es posible que no siempre necesite almacenamiento en búfer, por lo tanto, la respuesta sería No, en algunos casos es sólo por encima.

Hay otra razón por la que es "No" y puede ser más grave. BufferedInputStream (o BufferedReader) puede causar fallas impredecibles cuando se usa con un socket de red cuando también ha habilitado un tiempo de espera en el socket. El tiempo de espera puede ocurrir mientras lee un paquete. Ya no podrá acceder a los datos que se transfirieron a ese punto, incluso si sabía que había una cantidad de bytes distinta de cero (consulte java.net.SocketTimeoutException, que es una subclase de java.io.InterruptedIOException, por lo que tiene disponible la variable bytesTransferred).

Si se pregunta cómo podría ocurrir un tiempo de espera de socket al leer, solo piense en llamar al método read(bytes[]) y el paquete original que contiene el mensaje terminó dividido pero uno de los paquetes parciales se retrasa más allá del tiempo de espera (o porción restante del tiempo de espera). Esto puede suceder con más frecuencia cuando se vuelve a aplicar algo que implementa java.io.DataInput (cualquiera de las lecturas para valores de bytes múltiples, como readLong() o readFully() o el método BufferedReader.readLine()).

Tenga en cuenta que java.io.DataInputStream también es un mal candidato para las secuencias de socket que tienen un tiempo de espera ya que tampoco se comporta bien con las excepciones de tiempo de espera.

+1

En cuanto a BufferedInputStream y BufferedReader, este es el mito urbano. Si obtiene un tiempo de espera de lectura, (i) está leyendo, ergo, el búfer interno estaba vacío; de lo contrario, no estaría leyendo; (ii) no se recibieron datos dentro del período de tiempo de espera. Ergo no se pierde ningún dato. Pruébalo. – EJP

+0

@EJP: Me tienes realmente pensando en esto, sin embargo, todavía creo que esto puede ser un problema. Cuando la secuencia amortiguada realmente necesita hacer E/S (llenar el búfer), ese es el momento en que puede obtener una excepción de tiempo de espera y las variables internas para rastrear cuántos bytes en el búfer no se actualizarán. He intentado probar esto pero, aunque puedo replicar las excepciones de tiempo de espera, parece que todavía no puedo replicar una situación en la que 'bytesTransferred' no es cero. Hasta entonces, no puedo probar esto de una forma u otra. [He perdido datos con DataInputStream y timeout.] –

+0

@EJP: Quizás entonces leer una matriz de bytes desde el socket nunca dé como resultado un buffer parcialmente leído debido al tiempo de espera y luego 'bytesTransferred' nunca sea distinto de cero (de lo contrario, BufferredInputStream fallar). Este también puede ser un caso donde la implementación de JVM en diferentes plataformas/proveedores puede producir resultados diferentes. Acabo de probar en Windows 7 con Sun/Oracle Java. –

Cuestiones relacionadas