C# MemoryStream

C#

MemoryStream はメモリ上のバッファを読み書きできる入出力ストリームの実装です。ファイルやネットワークを介さず、シリアライズ/デシリアライズや一時データの操作に適しています。内部的にはバイト配列を保持し、Position/Length プロパティで読み書き位置やサイズを管理します。

=> 公式ドキュメント(.NET 8)

  • バッファの自動拡張:書き込むデータ量に応じて内部配列が動的に拡張されます。
  • 初期容量の指定:new MemoryStream(初期容量) であらかじめバッファサイズを確保可能です。
  • GetBuffer/ToArray:GetBuffer() で内部配列を直接参照、ToArray() で有効長分だけをコピーした新配列を取得します。
  • コンストラクタの publiclyVisible 引数で、非公開バッファとして動作させられます。falseだとバッファは非公開となりGetBuffer()が使えなくなります。
  • コンストラクタの writable 引数で、読み取り専用バッファとして動作させられます。
  • Position/Length プロパティ:現在の読み書き位置や有効データ長を自在に操作できます。

使いどころ

画像ファイルをオンメモリで

C#
using var image = Image.FromFile("input.jpg");
using var ms = new MemoryStream();
image.Save(ms, ImageFormat.Png);  // メモリ上にPNG形式で保存
byte[] pngBytes = ms.ToArray();   // バイト配列として取得し、API送信などに使う

バイナリデータのシリアライズ/デシリアライズ

C#
var obj = new MySerializableClass { Name = "John", Age = 42 };
var formatter = new BinaryFormatter();

using var ms = new MemoryStream();
formatter.Serialize(ms, obj);      // オブジェクトをバイナリに変換
byte[] serialized = ms.ToArray();  // バイト配列として保存やAPI送信などで使う

PDFの生成ライブラリなどと連携する

C#
using var ms = new MemoryStream();
var doc = new PdfDocument();  // PDF生成ライブラリの例
PdfPage page = doc.AddPage();
//
// PDFページの生成処理...
//
doc.Save(ms);  // メモリ上にPDFを生成
byte[] pdfBytes = ms.ToArray();  // ダウンロードやメール添付に使える

Zipライブラリと連携する

Zip圧縮ライブラリ System.IO.Compression と連携を行います。

C#
using var ms = new MemoryStream();
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
    var entry = archive.CreateEntry("sample.txt");
    using var writer = new StreamWriter(entry.Open());
    writer.Write("Hello World!");
    // ...
}
// ms に ZIP ファイルが格納されている

このコード例では、ZipArchiveのコンストラクタの第3引数 leaveOpen がtrueになっていますので、ZipArchive の using を抜けた後もZIPファイルは保持されています。
因みに第3引数 leaveOpen が false だと、ZipArchive の using を抜けたところで ms.dispose() が呼ばれてしまうため、それ以降 ms にはアクセスできません。

使いどころのまとめ

  • Stream を要求する API に、ファイルを使わずにデータを受け渡したい
  • バイナリデータをメモリ上で一時的に加工・変換したい
  • ファイル I/O のオーバーヘッドやセキュリティリスクを避けたい
  • テスト時のモックで FileStream を使いたくない

コメント

タイトルとURLをコピーしました