C’est un peu plus délicat que ce que j’avais imaginé au départ. J’essaie de lire n octets à partir d’un stream.
MSDN affirme que Read n’a pas à renvoyer n octets, il doit simplement renvoyer au moins 1 octets et au maximum n octets, 0 octet étant le cas particulier d’atteindre la fin du stream.
En général, j’utilise quelque chose comme
var buf = new byte[size]; var count = stream.Read (buf, 0, size); if (count != size) { buf = buf.Take (count).ToArray (); } yield return buf;
J’espère avoir exactement la size
octets, mais selon les spécifications, FileStream serait également autorisé à renvoyer un grand nombre de morceaux d’un octet. Cela doit être évité.
Une façon de résoudre ce problème serait de disposer de 2 mémoires tampons, une pour la lecture et une pour la collecte des morceaux jusqu’à l’obtention du nombre d’octets demandé. C’est un peu lourd cependant.
J’ai aussi jeté un coup d’œil à BinaryReader mais ses spécifications n’indiquent pas clairement que n octets seront retournés à coup sûr.
Pour clarifier: bien sûr, à la fin du stream, le nombre d’octets renvoyés peut être inférieur à la size
– ce n’est pas un problème. Je parle seulement de ne pas recevoir n octets même s’ils sont disponibles dans le stream.
Une version légèrement plus lisible:
int offset = 0; while (offset < count) { int read = stream.Read(buffer, offset, count - offset); if (read == 0) throw new System.IO.EndOfStreamException(); offset += read; }
Ou écrit en tant que méthode d'extension pour la classe Stream
:
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; } }
Simplement; vous faites une boucle;
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!
Après cela, buf
aurait dû être rempli avec exactement la bonne quantité de données du stream, ou aurait jeté un EOF.