Una forma elegante de consumir (todos los bytes de un) BinaryReader?


¿Hay un elegante para emular el método StreamReader.ReadToEnd con BinaryReader? Tal vez para poner todos los bytes en una matriz de bytes?

Hago esto:

read1.ReadBytes((int)read1.BaseStream.Length);

...pero debe haber una manera mejor.

Author: SamFisher83, 2011-12-23

4 answers

Simplemente haga:

byte[] allData = read1.ReadBytes(int.MaxValue);

La documentación dice que leerá todos los bytes hasta que se alcance el final de la secuencia.


Actualizar

Aunque esto parece elegante, y la documentación parece indicar que esto funcionaría, la implementación real (verificada en.NET 2, 3.5 y 4) asigna una matriz de bytes de tamaño completo para los datos, lo que probablemente causará un OutOfMemoryException en un sistema de 32 bits.

Por lo tanto, yo diría que en realidad no hay una manera elegante.

En su lugar, recomendaría la siguiente variación de la respuesta de @iano. Esta variante no se basa en. NET 4:
Cree un método de extensión para BinaryReader (o Stream, el código es el mismo para ambos).

public static byte[] ReadAllBytes(this BinaryReader reader)
{
    const int bufferSize = 4096;
    using (var ms = new MemoryStream())
    {
        byte[] buffer = new byte[bufferSize];
        int count;
        while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
            ms.Write(buffer, 0, count);
        return ms.ToArray();
    }

}
 81
Author: Scott Rippey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-05 08:56:20

No hay una manera fácil de hacer esto con BinaryReader. Si no sabes el conteo que necesitas leer antes de tiempo, una mejor apuesta es usar MemoryStream:

public byte[] ReadAllBytes(Stream stream)
{
    using (var ms = new MemoryStream())
    {
        stream.CopyTo(ms);
        return ms.ToArray();
    }
}

Para evitar la copia adicional al llamar a ToArray(), podría devolver el Position y el búfer, a través de GetBuffer().

 62
Author: iano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-06 01:05:46

Para copiar el contenido de una secuencia a otra, he resuelto leer" algunos " bytes hasta que se alcanza el final del archivo:

private const int READ_BUFFER_SIZE = 1024;
using (BinaryReader reader = new BinaryReader(responseStream))
{
    using (BinaryWriter writer = new BinaryWriter(File.Open(localPath, FileMode.Create)))
    {
        int byteRead = 0;
        do
        {
            byte[] buffer = reader.ReadBytes(READ_BUFFER_SIZE);
            byteRead = buffer.Length;
            writer.Write(buffer);
            byteTransfered += byteRead;
        } while (byteRead == READ_BUFFER_SIZE);                        
    }                
}
 3
Author: Seraphim's,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-16 13:26:10

Otro enfoque para este problema es usar métodos de extensión de C#:

public static class StreamHelpers
{
   public static byte[] ReadAllBytes(this BinaryReader reader)
   {
      // Pre .Net version 4.0
      const int bufferSize = 4096;
      using (var ms = new MemoryStream())
      {
        byte[] buffer = new byte[bufferSize];
        int count;
        while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
            ms.Write(buffer, 0, count);
        return ms.ToArray();
      }

      // .Net 4.0 or Newer
      using (var ms = new MemoryStream())
      {
         stream.CopyTo(ms);
         return ms.ToArray();
      }
   }
}

El uso de este enfoque permitirá tanto código reutilizable como legible.

 -1
Author: mageos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-29 02:51:10