2012-09-05 11 views
7

Según Java documentation, el parámetroreadlimit del método de marca en el servidor de la clase InputStream para el conjunto "el límite máximo de bytes que puede ser leído antes de que la posición de la marca no es válida.". Tengo un archivo llamado sample.txt cuyo contenido es "hola". Y escribí este código:Java: InputStream marca de límite

import java.io.*; 
public class InputStream{ 
public static void main (String[] args) throws IOException { 
    InputStream reader = new FileInputStream("sample.txt"); 
    BufferedInputStream bis = new BufferedInputStream(reader); 
    bis.mark(1); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.reset(); 
    System.out.println((char)bis.read()); 
} 
} 

La salida es "h". Pero si después del marca el método leer más de un octeto, ¿no debería obtener un error para el restablecer la llamada al método cero?

Respuesta

5

Me gustaría poner esto a la documentación de error.

El doc no paramétrico para BufferedInputStream es "Ver el contrato general del método de marca de InputStream", que para mí indica que BufferedInputStream no se comporta de manera diferente, a pesar del parámetro doc.

Y el contrato general, según lo especificado por InputStream, es

Los argumentos readlimit dice este flujo de entrada para permitir que la cantidad de bytes que deben leerse antes de que la posición de la marca se invalida [...] es la corriente no es necesario recordar ningún dato en absoluto si se leen más bytes leídos de la secuencia

En otras palabras, readlimit es una sugerencia; la transmisión es gratuita y no promete demasiado.

+0

¿Conoces alguna implementación de InputStream para reproducir el escenario en el que si leo más bytes que los establecidos con mark() se lanzará una excepción? –

1

En cuanto a la implementación de BufferedInputStream, se describe la importancia de la posición del marcador en los JavaDocs (del markpos campo de protección):

[markpos es] el valor del campo pos en el momento de la se llamó el último mark método.

Este valor está siempre en el rango -1 hasta pos. Si no hay una posición marcada en la secuencia de entrada, este campo es -1. Si hay una posición marcada en la secuencia de entrada, entonces buf[markpos] es el primer byte que se suministrará como entrada después de una operación reset. Si markpos no es -1, a continuación, todos los bytes desde posiciones buf[markpos] a través de buf[pos-1] debe permanecer en la matriz del separador (aunque pueden ser movidos a otro lugar en la matriz de memoria intermedia, con ajustes adecuados a los valores de count, pos, y markpos); no pueden descartarse a menos que y hasta que la diferencia entre pos y markpos exceda marklimit.

Espero que esto ayude. Eche un vistazo a las definiciones de read, reset y el método privado fill en la clase para ver cómo se relaciona todo.

En resumen, solo cuando la clase recupere más datos para llenar su memoria intermedia se tendrá en cuenta la posición de la marca. Se invalidará correctamente si se leen más bytes que la llamada a mark permitida. Como resultado, las llamadas al read no activarán necesariamente el comportamiento publicitado en los comentarios públicos de JavaDoc.

1

Esto parece un error sutil. Si se reduce el buffer SizeY obtendrá un IOException

public static void main(String[] args) throws IOException { 
    InputStream reader = new ByteArrayInputStream(new byte[]{1, 2, 3, 4, 5, 6, 7, 8}); 
    BufferedInputStream bis = new BufferedInputStream(reader, 3); 
    bis.mark(1); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.reset(); 
    System.out.println((char)bis.read()); 
} 
2

Si nos fijamos en la source, en particular el método de relleno(), se puede ver (después de un tiempo!) Que sólo invalida el blanco cuando se absolutamente necesario, es decir, es más tolerante de lo que la documentación podría sugerir.

... 
else if (pos >= buffer.length) /* no room left in buffer */ 
    if (markpos > 0) { /* can throw away early part of the buffer */ 
    int sz = pos - markpos; 
    System.arraycopy(buffer, markpos, buffer, 0, sz); 
    pos = sz; 
    markpos = 0; 
    } else if (buffer.length >= marklimit) { 
    markpos = -1; /* buffer got too big, invalidate mark */ 
    pos = 0;  /* drop buffer contents */ 
    .... 

El tamaño de búfer predeterminado es relativamente grande (8K), por lo que la invalidación no se activará en su ejemplo.

Cuestiones relacionadas