2009-06-04 6 views
9

Jusqu'à maintenant je compte 12 LoCs. Pourriez-vous le rendre plus petit?Comment copier un flux dans un tableau d'octets avec le plus petit code C#?

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); 
     } 
    } 
} 

Répondre

30

Il y a une méthode statique qui peut le faire pour vous en un seul appel.

var data = File.ReadAllBytes(fileName); 

Alternativement, une méthode qui fonctionne pour tout Stream (qui renvoie sa longueur) serait:

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

Pour les flux qui n'ont pas une longueur bien définie (par exemple NetworkStream), et donc lever une exception sur l'appel stream.Length, cela ne fonctionne bien sûr pas. La solution légèrement plus compliquée présentée dans la réponse de Jon Skeet est alors ce que vous voulez probablement.

+5

Tous les flux ne renvoient pas leur longueur si ... –

+0

data = binaryReader.ReadBytes (stream.Length); devrait être data = br.ReadBytes (stream.Length); – OneSHOT

+0

Oui, bravo. Typo évident. – Noldorin

27

Comment « bout un:

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

+1 Nicely done :) –

+2

Bien qu'il ne fonctionne que pour les fichiers bien sûr ... elle correspond à la code dans la question originale, mais pas le titre de la question :) –

+0

Bon point.Peut-être que si je m'ennuie plus tard, je l'exprimerai en termes d'une fonction qui accepte un flux ouvert en entrée - pour tous les extraits de code, personne n'a pris la peine de sortir une signature de fonction pour le moment. –

8

Tout en ne réduisant pas le COL (je ne l'avais jamais utiliser comme motivation primaire), vous pouvez réduire les usings comme ceci:

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

Bon tour, merci. –

+0

Belle astuce avec les différentes déclarations utilisant –

+3

"Pourquoi est-ce important si cela fonctionne?" Cela n'a pas d'importance tant que vous n'avez pas à maintenir le code ;-) – fretje

15

Réduire vos lignes de code est assez simple ici (tout en travaillant avec des flux arbitraires, plutôt que des fichiers):

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

de toute évidence, il est beaucoup plus efficace à lire dans un tampon que de lire un octet à la fois, mais cela réduit le nombre de déclarations (comme vous don pas besoin de déclarer à la fois un tampon et une variable pour contenir la valeur de retour de Stream). Appeler MemoryStream.ToArray() est plus simple que de lire dans un tableau nouvellement construit. L'utilisation d'un tampon est cependant plus agréable. Notez que nous ne avons pas vraiment besoin 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 vous voulez être vraiment brutale, nous pourrions réduire le nombre de using déclarations (soit avec solution):

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(); 
} 

Mais c'est juste méchant :)

Une autre option est bien sûr d'utiliser une bibliothèque telle que MiscUtil qui a une méthode pour lire entièrement à partir d'un flux :) La méthode utilitaire peut être aussi simple que ceci:

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(); 
    } 
} 

Notez que ce ne ferme le flux - l'appelant doit faire.

2

Il suffit d'utiliser la méthode CopyTo du Stream copier sur un MemoryStream et obtenir le tableau:

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

     byte[] transparentPng = memoryStream.ToArray(); 
    } 
} 
Questions connexes