「ファイルを受け取るメソッドをテストしたいが、わざわざ物理ファイルを作るのは面倒」という場面や、「ネットワークから取得した想定の文字列データを、ファイルと同じように処理したい」というケースがあります。
そのような場合、文字列(string)をバイト配列に変換し、それを MemoryStream に渡すことで、あたかもファイルストリームであるかのように扱うことができます。
実装サンプル:文字列をファイルに見立てて読み込む
以下のコードでは、複数行の文字列データを MemoryStream に変換し、それを StreamReader で1行ずつ読み込んで処理しています。
サンプルコード
using System;
using System.IO;
using System.Text;
public class Program
{
public static void Main()
{
// 1. テスト用の複数行文字列
// 本来はファイルに入っているようなデータを文字列として定義
string dummyData = @"[ServerConfig]
Host=192.170.1.10
Port=8080
Timeout=300
Environment=Production";
Console.WriteLine("--- ストリーム処理開始 ---");
// 2. 自作メソッドで文字列からStreamReaderを作成
using (var reader = CreateStreamReader(dummyData))
{
// ファイルを読んでいるのと全く同じように扱える
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
// 分かりやすく装飾して出力
Console.WriteLine($"読み込み行: <{line}>");
}
}
}
/// <summary>
/// 文字列を元にStreamReaderを作成して返すヘルパーメソッド
/// </summary>
static StreamReader CreateStreamReader(string inputString)
{
// A. 文字列をバイト配列に変換 (UTF-8)
byte[] byteArray = Encoding.UTF8.GetBytes(inputString);
// B. バイト配列をメモリ上のストリーム(MemoryStream)に展開
// これにより、ファイルI/OなしでStreamとして振る舞う
var stream = new MemoryStream(byteArray);
// C. ストリームを読み込むReaderを作成して返す
return new StreamReader(stream);
}
}
実行結果
--- ストリーム処理開始 ---
読み込み行: <[ServerConfig]>
読み込み行: <Host=192.170.1.10>
読み込み行: <Port=8080>
読み込み行: <Timeout=300>
読み込み行: <Environment=Production>
解説とメリット
1. MemoryStream の役割
MemoryStream は、ディスク上のファイルではなく「メモリ上のバイト配列」を読み書きするためのクラスです。 コンストラクタ new MemoryStream(byte[] buffer) を使うことで、既存のデータ(バイト配列)をラップしたストリームを即座に作成できます。
2. テスト容易性の向上
ファイル操作を行うクラスのテストコード(Unit Test)を書く際、実際に File.Open をしてしまうと、ファイルの準備や後片付けが必要になり、テストが遅く不安定になります。 引数を FileStream ではなく、抽象的な親クラスである Stream 型を受け取るように設計しておけば、テスト時にはこのテクニックを使って MemoryStream を渡すだけで、ファイルアクセスなしにロジックの検証が可能になります。
3. 文字コードに注意
文字列をバイト配列にする際、Encoding.UTF8.GetBytes(str) を使用していますが、読み手である StreamReader もデフォルトで UTF-8 として読み取ります。 もし Shift-JIS などのデータをシミュレーションしたい場合は、バイト変換時と StreamReader 作成時の両方でエンコーディングを合わせる必要があります。
