StringReaderクラスStringWriterクラスは、文字列を一種のストリームとみなして読み込み・書き込みを行うクラスです。 これらのクラスの一番のポイントは、TextReader/TextWriterの派生クラスである点です。 StreamReaderクラスとStreamWriterクラスもTextReader/TextWriterから派生したクラスですが、これらのクラスと共通したメソッドを持つため、文字列のストリームであろうとファイルのストリームであろうと区別することなく同じ処理を行うことが出来ます。

また、StringReader/StringWriterを使うことによって、一時ファイルを使わずにメモリ上のでテキストの読み込み/書き込みを行うといったことも可能になります。

以下ではStringReader/StringWriterに固有な部分のみを解説します。 個々のメソッドの使い方など、基本的な操作についてはStreamReaderクラス・StreamWriterクラスを参照してください。

§1 StringReaderクラス

StringReaderクラスはStringクラスの文字列をストリームとみなして読み込みを行うクラスです。 コンストラクタに読み込みたい文字列を含むStringを指定することで、その文字列から読み込みを行うStringReaderのインスタンスを生成できます。

以下は、StringReaderとStreamReaderを使って、文字列およびファイルをXMLとして読み込み、要素"/foo/bar"のテキストを表示する例です。 XMLの読み込みは共通のメソッドである点に注目してください。

using System;
using System.IO;
using System.Xml;

class Sample {
  static void Main()
  {
    string xmlText = "<?xml version=\"1.0\"?><foo><bar>hoge</bar></foo>";

    // Stringから読み込む
    using (StringReader r = new StringReader(xmlText)) {
      ReadXml(r);
    }

    // ファイルから読み込む
    using (StreamReader r = new StreamReader("sample.xml")) {
      ReadXml(r);
    }
  }

  static void ReadXml(TextReader reader)
  {
    XmlDocument document = new XmlDocument();

    document.Load(reader);

    Console.WriteLine(document.InnerXml);
    Console.WriteLine(document.SelectSingleNode("/foo/bar/text()").Value);
  }
}
sample.xmlの内容
<?xml version="1.0"?>
<foo>
  <baz>hoge</baz>
  <bar>piyo</bar>
</foo>
実行結果
<?xml version="1.0"?><foo><bar>hoge</bar></foo>
hoge
<?xml version="1.0"?><foo><baz>hoge</baz><bar>piyo</bar></foo>
piyo

StringReaderを使うことにより、StreamReaderのメソッドを使ってファイルから読み込むのと同様に文字列を扱うことができます。 次の例では、既存の文字列を読み込み、一行毎に分割して表示しています。

StringReaderを使って文字列を行ごとに分割する例
using System;
using System.IO;
using System.Xml;

class Sample {
  static void Main()
  {
    // 複数の"行"が含まれる文字列
    string text = "foo\r\nbar\r\nhoge\r\npiyo";

    using (StringReader r = new StringReader(text)) {
      for (;;) {
        // StringReaderを使って文字列textから"一行"ずつ読み込む
        string line = r.ReadLine();

        if (line == null) break;

        Console.WriteLine(line);
      }
    }
  }
}
実行結果
foo
bar
hoge
piyo


§2 StringWriterクラス

StringWriterクラスStringBuilderクラスを出力先のストリームとみなして書き込みを行うクラスです。 Stringクラスは不変であるため、代わりにStringBuilderが書き込み先に使用されます。 コンストラクタに書き込み先となるStringBuilderを指定することで、そのStringBuilderへ書き込みを行うStringWriterのインスタンスを生成できます。

以下は、StringWriterとStreamWriterを使って、作成したXMLドキュメントをファイルと文字列に書き出す例です。 XMLドキュメントの作成と書き込みは共通のメソッドである点に注目してください。

using System;
using System.IO;
using System.Text;
using System.Xml;

class Sample {
  static void Main()
  {
    StringBuilder sb = new StringBuilder();

    // StringBuilderに書き込む
    using (StringWriter w = new StringWriter(sb)) {
      WriteXml(w);
    }

    Console.WriteLine(sb);

    // ファイルに書き込む
    using (StreamWriter w = new StreamWriter("sample.xml")) {
      WriteXml(w);
    }
  }

  static void WriteXml(TextWriter writer)
  {
    XmlDocument document = new XmlDocument();

    document.LoadXml("<?xml version=\"1.0\"?><foo><bar>hoge</bar></foo>");

    document.Save(writer);
  }
}
実行結果
<?xml version="1.0"?>
<foo>
  <bar>hoge</bar>
</foo>
sample.xmlに保存される内容
<?xml version="1.0"?>
<foo>
  <bar>hoge</bar>
</foo>

StringWriterでは、コンストラクタにStringBuilderを指定しなくてもインスタンスを生成することが出来ます。 この場合、暗黙的にStringBuilderが生成されStringWriterで使用されます。 書き込んだ内容は、GetStringBuilderメソッドToStringメソッドを使って取得できます。

using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    using (StringWriter w = new StringWriter()) {
      w.Write("The quick brown fox");
      w.WriteLine(" jumps over the lazy dog");

      Console.WriteLine("Length: {0}", w.GetStringBuilder().Length);
      Console.WriteLine("Capacity:{0}", w.GetStringBuilder().Capacity);
      Console.WriteLine(w.ToString());
    }
  }
}
実行結果
Length: 44
Capacity:86
The quick brown fox jumps over the lazy dog