MemoryStream はメモリ上のバッファを読み書きできる入出力ストリームの実装です。ファイルやネットワークを介さず、シリアライズ/デシリアライズや一時データの操作に適しています。内部的にはバイト配列を保持し、Position/Length プロパティで読み書き位置やサイズを管理します。
- バッファの自動拡張:書き込むデータ量に応じて内部配列が動的に拡張されます。
- 初期容量の指定:
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 を使いたくない
コメント