2009-06-04 8 views
9

Hasta ahora estoy contando 12 LoCs. ¿Podrías hacerlo más pequeño?Cómo copiar una secuencia a una matriz de bytes con el código C# más pequeño?

using (Stream fileStream = File.OpenRead(fileName)) 
{ 
    using (BinaryReader binaryReader = new BinaryReader(fileStream)) 
    { 
     using (MemoryStream memoryStream = new MemoryStream()) 
     { 
      byte[] buffer = new byte[256]; 
      int count; 
      int totalBytes = 0; 
      while ((count = binaryReader.Read(buffer, 0, 256)) > 0) 
      { 
       memoryStream.Write(buffer, 0, count); 
       totalBytes += count; 
      } 
      memoryStream.Position = 0; 
      byte[] transparentPng = new byte[totalBytes]; 
      memoryStream.Read(transparentPng, 0, totalBytes); 
     } 
    } 
} 

Respuesta

30

Hay un método estático que puede hacer esto para usted en una llamada.

var data = File.ReadAllBytes(fileName); 

Alternativamente, un método que funciona para cualquier Stream (que devuelve su longitud) sería:

byte[] data; 
using (var br = new BinaryReader(stream)) 
    data = br.ReadBytes((int)stream.Length); 

Para las corrientes que no tienen una longitud bien definida (por ejemplo NetworkStream), y por lo tanto, plantear una excepción al llamar al stream.Length, esto por supuesto no funciona. La solución un poco más complicada presentada en la respuesta de Jon Skeet es entonces lo que probablemente desee.

+5

No todas las secuencias devuelven su longitud ... –

+0

data = binaryReader.ReadBytes (stream.Length); debe ser data = br.ReadBytes (stream.Length); – OneSHOT

+0

Sí, aplausos. Obvio error tipográfico – Noldorin

27

¿Qué tal uno:

byte[] result = File.ReadAllBytes(fileName); 
+0

+1 bien hecho :) –

+2

A pesar de que sólo funciona para archivos de curso ... que coincide con la código en la pregunta original, pero no el título de la pregunta :) –

+0

Buen punto.Tal vez si me aburro más tarde lo expresaré en términos de una función que acepta una transmisión abierta como entrada: para todos los fragmentos de código, nadie se molestó en poner una firma de función todavía. –

8

Aunque no es la reducción de la LOC (nunca usaría esto como una motivación primaria), puede contraer las usings así:

using (Stream fileStream = File.OpenRead(fileName)) 
using (BinaryReader binaryReader = new BinaryReader(fileStream)) 
using (MemoryStream memoryStream = new MemoryStream()) 
{ 
    byte[] buffer = new byte[256]; 
    int count; 
    int totalBytes = 0; 
    while ((count = binaryReader.Read(buffer, 0, 256)) > 0) 
    { 
     memoryStream.Write(buffer, 0, count); 
     totalBytes += count; 
    } 
    memoryStream.Position = 0; 
    byte[] transparentPng = new byte[totalBytes]; 
    memoryStream.Read(transparentPng, 0, totalBytes);  
} 
+0

Buen truco, gracias. –

+0

Buen truco con las diferentes declaraciones de uso –

+3

"¿Por qué importa si funciona?" No importa, siempre y cuando no tenga que mantener el código ;-) – fretje

15

La reducción de sus líneas de código es bastante simple aquí (mientras trabaja con las corrientes arbitrarias, en lugar de archivos):

using (Stream fileStream = File.OpenRead(fileName)) 
using (MemoryStream memoryStream = new MemoryStream()) 
{ 
    int byteRead; 
    while ((byteRead = fileStream.ReadByte()) != -1) 
    { 
     memoryStream.WriteByte(byteRead); 
    } 
    return memoryStream.ToArray(); 
} 

Obviamente es mucho más eficiente a leer en un búfer de leer un byte a la vez, pero esto reduce el número de declaraciones (como Don no es necesario declarar un buffer y una variable para contener el valor de retorno de Stream). Llamar al MemoryStream.ToArray() es más simple que leer en una matriz recién construida.

Sin embargo, usar un buffer es más agradable. Tenga en cuenta que en realidad no necesitamos BinaryReader:

using (Stream fileStream = File.OpenRead(fileName)) 
using (MemoryStream memoryStream = new MemoryStream()) 
{ 
    byte[] buffer = new byte[8192]; 
    int bytesRead; 
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0) 
    { 
     memoryStream.Write(buffer, 0, bytesRead); 
    } 
    return memoryStream.ToArray(); 
} 

Si quieres ser realmente brutal, que podría reducir el número de using declaraciones (ya sea con solución):

using (Stream fileStream = File.OpenRead(fileName), 
       memoryStream = new MemoryStream()) 
{ 
    byte[] buffer = new byte[8192]; 
    int bytesRead; 
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0) 
    { 
     memoryStream.Write(buffer, 0, bytesRead); 
    } 
    return ((MemoryStream)memoryStream).ToArray(); 
} 

pero eso es simplemente desagradable :)

Otra opción, por supuesto, es utilizar una biblioteca como MiscUtil que tiene un método para leer completamente desde una secuencia :) El método de utilidad puede ser tan simple como esto:

public static byte[] ReadFully(this Stream stream) 
{ 
    using (MemoryStream memoryStream = new MemoryStream()) 
    { 
     byte[] buffer = new byte[8192]; 
     int bytesRead; 
     while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) 
     { 
      memoryStream.Write(buffer, 0, bytesRead); 
     } 
     return memoryStream.ToArray(); 
    } 
} 

Tenga en cuenta que este no cierra la corriente - la persona que llama debe hacer eso.

2

sólo tiene que utilizar el método de la StreamCopyTo para copiar en un MemoryStream, y obtener la matriz:

using (var fileStream = File.OpenRead(fileName)) 
{ 
    using (var memoryStream = new MemoryStream()) 
    { 
     fileStream.CopyTo(memoryStream); 
     memoryStream.Seek(0, SeekOrigin.Begin); 

     byte[] transparentPng = memoryStream.ToArray(); 
    } 
} 
Cuestiones relacionadas