1. ホーム
  2. c#

[解決済み] ストリームからのバイト配列の作成

2022-03-18 07:58:59

質問

入力ストリームからバイト配列を作成する場合、どのような方法が好ましいですか?

以下は、.NET 3.5を使った私の現在の解決策です。

Stream s;
byte[] b;

using (BinaryReader br = new BinaryReader(s))
{
    b = br.ReadBytes((int)s.Length);
}

やはりストリームのチャンクを読み書きするのが良いのでしょうか?

どのように解決するのですか?

それは、あなたが信頼できるかどうかにかかっています。 s.Length . 多くのストリームでは、どれだけのデータがあるのかわかりません。そのような場合、そして.NET 4以前であれば、私はこのようなコードを使用します。

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16*1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

.NET 4以上なら Stream.CopyTo これは、基本的に私のコードのループと同じです。 MemoryStream を呼び出す。 stream.CopyTo(ms) を返し、さらに ms.ToArray() . 仕事は完了です。

なぜ私の回答が他の人より長いのか、その理由を説明すべきかもしれません。 Stream.Read は、要求されたものすべてを読み取ることを保証するものではありません。例えば、ネットワークストリームから読み込む場合、たとえすぐにデータが増えるとしても、1パケット分を読み込んで戻るかもしれません。 BinaryReader.Read はストリームの終わりか、指定したサイズまで進みますが、それでも最初にサイズを知っておく必要があります。

上記のメソッドは、読み出し(および MemoryStream ) データがなくなるまで そして MemoryStream を使用して、データのコピーを配列で返します。もし、最初にサイズを知っていれば - あるいは 思う を作成することができます。 MemoryStream をそのサイズにする必要があります。同様に、最後にチェックを入れて、ストリームの長さがバッファと同じサイズであれば ( MemoryStream.GetBuffer ということで、バッファを返せばいいわけです。ですから、上記のコードは最適化されているとは言えませんが、少なくとも正しいものでしょう。ストリームのクローズは呼び出し元が行うべきで、このコードはその責任を負いません。

参照 この記事 をご覧ください(別の実装もあります)。