2011-09-22 16 views
7

Bu, hayal ettiğimden biraz daha zor. Bir akıştan n bayt okumaya çalışıyorum.Bir akıştan tam olarak n bayt okuyabilir miyim?

MSDN claims nolu okunmanın n bayt döndürmesi gerekmediğinden, yalnızca en az 1 ve en çok n bayt döndürmelidir; 0 bayt, akışın sonuna erişme özel durumudur.

Genellikle, ben tam olarak size bayt için değil Spec FileStream tarafından umuduyla

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

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

yield return buf; 

gibi bir şey değilim kullanıyorum yanı 1 baytlık parçalar çok sayıda dönmesine izin verilmesi olacaktır. Bu kaçınılmalıdır.

Bunu çözmenin bir yolu, istenen bir bayt sayısı elde edilene kadar, bir tane okuma için ve bir tanesi toplanacak olan 2 arabelleğe sahip olmak olacaktır. Yine de biraz hantal.

Ayrıca BinaryReader'a da baktım, ancak özellikleri de n baytların kesin olarak döndürüleceğini açıkça belirtmiyor.

Netleştirmek için: Tabii ki, akış sonunda, döndürülen bayt sayısı size'dan daha az olabilir - bu sorun değil. Sadece akışta bulunsalar bile n bayt almadığımdan bahsediyorum.

+0

'BinaryReader.ReadBytes (int) 'istenen bayt sayısını verir; Akış daha erken biterse, o noktaya kadar okuduğu şeyi (istendiği kadar az) döndürecektir. –

+0

@bosonix Bu kullanışlı olurdu. Bu bilgi için bir kaynağın var mı? – mafu

+1

bu, MSDN sayfasında belirtilir https://msdn.microsoft.com/en-us/library/system.io.binaryreader.readbytes(v=vs.110).aspx ve ayrıca sökülmüş koduna da baktım. –

cevap

11

Biraz daha okunabilir versiyon:

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

ya Stream sınıfı için bir uzantı yöntemi olarak yazılır:

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

Basitçe; Döngü Bundan sonra

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! 

, buf akışından verilerin tam olarak doğru miktarda doldurulur olması gerekirdi, ya da EOF atılmış olacaktır.

İlgili konular