2009-06-04 4 views
9

Do tej pory liczę 12 LoC. Czy możesz go zmniejszyć?Jak skopiować jeden strumień do tablicy bajtów przy użyciu najmniejszego kodu 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); 
     } 
    } 
} 

Odpowiedz

30

Jest statyczna metoda, która może zrobić to za Ciebie w jednej rozmowy.

var data = File.ReadAllBytes(fileName); 

Alternatywnie, metoda, która działa na każdym Stream (to zwraca jej długości) może być:

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

Do strumieni, które nie mają ściśle określoną długość (np NetworkStream) i w ten sposób podnieść wyjątek na wywołanie stream.Length, to oczywiście nie działa. Nieco bardziej skomplikowanym rozwiązaniem przedstawionym w odpowiedzi Jona Skeeta jest to, czego prawdopodobnie chcesz.

+5

Nie wszystkie strumienie zwracają jednak swoją długość ... –

+0

data = binaryReader.ReadBytes (stream.Length); powinno być data = br.ReadBytes (stream.Length); – OneSHOT

+0

Tak, okrzyki. Oczywiste literówki. – Noldorin

27

Jak „bout jeden:

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

+1 Ładnie zrobione :) –

+2

Mimo to działa tylko dla plików oczywiście ... to pasuje do kod w pierwotnym pytaniu, ale nie tytuł pytania :) –

+0

Dobra uwaga.Może, jeśli później się znudzę, wyrażę to w kategoriach funkcji, która akceptuje otwarty strumień jako dane wejściowe - dla wszystkich fragmentów kodu, których nikt nie zawracał sobie głowy wystawieniem jeszcze sygnatury funkcji. –

8

Chociaż nie zmniejszając LOC (nigdy nie używać tego jako podstawowej motywacji), można zwinąć usings tak:

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

Dobra sztuczka, dzięki. –

+0

Dobra sztuczka z różnymi instrukcjami użycia –

+3

"dlaczego to ma znaczenie, jeśli to działa?" Nie ma to znaczenia, dopóki nie musisz utrzymywać kodu ;-) – fretje

15

zmniejszając linii kodu jest dość prosta tutaj (podczas gdy nadal pracuje z dowolnych strumieni, a nie tylko pliki):

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

Oczywiście jest to dużo bardziej wydajny czytać w buforze niż czytać bajt na raz, ale to zmniejsza liczbę wypowiedzi (jako don Trzeba zadeklarować zarówno bufor, jak i zmienna przechowująca wartość zwrotną ze strumienia). Wywołanie MemoryStream.ToArray() jest prostsze niż czytanie do nowo utworzonej tablicy.

Korzystanie z bufora jest jednak przyjemniejsze. Zauważ, że naprawdę nie trzeba 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(); 
} 

Jeśli chcesz być naprawdę brutalny, moglibyśmy zmniejszyć liczbę using sprawozdania (albo roztwór):

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

Ale to po prostu nieprzyjemny :)

Inną opcją jest oczywiście użycie biblioteki, takiej jak MiscUtil, która ma metodę pełnego odczytu ze strumienia :) Metoda użyteczności może być tak prosta jak ta:

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

pamiętać, że ten nigdy zamyka strumień - rozmówca powinien zrobić.

2

Wystarczy użyć sposobu StreamCopyTo skopiować do MemoryStream i uzyskać tablicy:

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

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