Stream.Readの契約は、私が多くの人をつまずかせるのを見てきました。
// Read 8 bytes and turn them into a ulong
byte[] data = new byte[8];
stream.Read(data, 0, 8); // <-- WRONG!
ulong data = BitConverter.ToUInt64(data);
これは間違っている理由は、それがあるStream.Read
読み込みます、最大で指定されたバイト数を、しかしである、完全無料の別の7つのバイトは、ストリームの終了前に利用可能である場合でも、ちょうど1バイトを読み取ります。
それはに非常に類似したこのルックスことを助けないStream.Write
、され、それは例外なく返した場合の保証は、すべてのバイトを書かれているし。また、上記のコードがほとんど常に機能することも役に立ちません。そしてもちろん、正確にNバイトを正確に読み取るための既製の便利な方法がないことは役に立ちません。
そのため、穴を塞ぎ、これに対する認識を高めるために、これを行う正しい方法の例を次に示します。
/// <summary>
/// Attempts to fill the buffer with the specified number of bytes from the
/// stream. If there are fewer bytes left in the stream than requested then
/// all available bytes will be read into the buffer.
/// </summary>
/// <param name="stream">Stream to read from.</param>
/// <param name="buffer">Buffer to write the bytes to.</param>
/// <param name="offset">Offset at which to write the first byte read from
/// the stream.</param>
/// <param name="length">Number of bytes to read from the stream.</param>
/// <returns>Number of bytes read from the stream into buffer. This may be
/// less than requested, but only if the stream ended before the
/// required number of bytes were read.</returns>
public static int FillBuffer(this Stream stream,
byte[] buffer, int offset, int length)
{
int totalRead = 0;
while (length > 0)
{
var read = stream.Read(buffer, offset, length);
if (read == 0)
return totalRead;
offset += read;
length -= read;
totalRead += read;
}
return totalRead;
}
/// <summary>
/// Attempts to read the specified number of bytes from the stream. If
/// there are fewer bytes left before the end of the stream, a shorter
/// (possibly empty) array is returned.
/// </summary>
/// <param name="stream">Stream to read from.</param>
/// <param name="length">Number of bytes to read from the stream.</param>
public static byte[] Read(this Stream stream, int length)
{
byte[] buf = new byte[length];
int read = stream.FillBuffer(buf, 0, length);
if (read < length)
Array.Resize(ref buf, read);
return buf;
}