2011-09-22 12 views
7

Esto es un poco más complicado de lo que había imaginado. Estoy tratando de leer n bytes de una secuencia.¿Cómo leo exactamente n bytes de una secuencia?

MSDN claims que Read no tiene que devolver n bytes, solo debe devolver al menos 1 y hasta n bytes, siendo 0 bytes el caso especial de llegar al final de la secuencia.

Por lo general, estoy usando algo así como

var buf = new byte[size]; 
var count = stream.Read (buf, 0, size); 

if (count != size) { 
    buf = buf.Take (count).ToArray(); 
} 

yield return buf; 

estoy esperando por exactamente size bytes, pero por espectrometría de FileStream se le permitiría devolver un gran número de trozos de 1 byte también. Esto debe ser evitado.

Una forma de resolver esto sería tener 2 almacenamientos intermedios, uno para leer y otro para recoger los fragmentos hasta que obtengamos el número solicitado de bytes. Eso es un poco engorroso sin embargo.

También eché un vistazo a BinaryReader pero su especificación tampoco indica claramente que se devolverán n bytes con seguridad.

Para aclarar: Por supuesto, al final de la secuencia, el número devuelto de bytes puede ser menor que size - eso no es un problema. Solo estoy hablando de no recibir n bytes aunque estén disponibles en la transmisión.

+0

el 'BinaryReader.ReadBytes (int)' devuelve el número de bytes solicitados; si la secuencia finaliza antes, devolverá lo que leyó hasta ese punto (por lo tanto, menos de lo solicitado). –

+0

@bosonix Eso sería conveniente. ¿Tienes una fuente para esta información? – mafu

+1

esto se especifica en la página de MSDN https://msdn.microsoft.com/en-us/library/system.io.binaryreader.readbytes(v=vs.110).aspx y también miré el código desensamblado. –

Respuesta

11

Una versión ligeramente más legible:

int offset = 0; 
while (offset < count) 
{ 
    int read = stream.Read(buffer, offset, count - offset); 
    if (read == 0) 
     throw new System.IO.EndOfStreamException(); 
    offset += read; 
} 

o escrita como un método de extensión para la clase Stream:

public static class StreamUtils 
{ 
    public static byte[] ReadExactly(this System.IO.Stream stream, int count) 
    { 
     byte[] buffer = new byte[count]; 
     int offset = 0; 
     while (offset < count) 
     { 
      int read = stream.Read(buffer, offset, count - offset); 
      if (read == 0) 
       throw new System.IO.EndOfStreamException(); 
      offset += read; 
     } 
     System.Diagnostics.Debug.Assert(offset == count); 
     return buffer; 
    } 
} 
9

Simplemente; tu bucle;

int read, offset = 0; 
while(leftToRead > 0 && (read = stream.Read(buf, offset, leftToRead)) > 0) { 
    leftToRead -= read; 
    offset += read; 
} 
if(leftToRead > 0) throw new EndOfStreamException(); // not enough! 

Después de esto, buf debería haber sido poblada con exactamente la cantidad correcta de los datos de la corriente, o se habrá tirado un EOF.

Cuestiones relacionadas