5

StreamReaders と StringReaders の組み合わせである 3 つの TextReaders があります。概念的には、それらを連結すると 1 つのテキスト ドキュメントになります。

単一の TextReader を受け取るメソッド (自分の制御下にない) を呼び出したい。複数の TextReader から連結 TextReader を作成する組み込みまたは簡単な方法はありますか?

(独自の TextReader サブクラスを作成することもできますが、かなりの作業量のように見えます。その場合は、それらすべてを一時ファイルに書き込んでから、単一の StreamReader で開くだけです。)

私が見逃しているこれに対する簡単な解決策はありますか?

4

1 に答える 1

6

これをまとめただけなので、非常に堅牢ではありませんが (エラー処理がないなど)、基本的なテスト ケースは機能します。

の拡張メソッドを作成することで機能しTextReader、1 秒かかる新しい TextReader クラスを返します。このクラスはRead()、最初のメソッドがなくなるまで内部的に呼び出し、次にRead()2 番目のメソッドの呼び出しを開始します。これを無期限に連鎖させることができます。

の完全な実装を提供するには、 、、およびTextReaderを実装するだけで済みます。他のすべてのメソッドは、特定の実装に依存して動作します。したがって、以下に示すように、独自のものを作成することはそれほど悪くありません。Read()Peek()Close()Dispose()Read()TextReader

これにより、既存の TextReader をラップするだけで、実際にそれらを呼び出して連結を実行するわけではないため、パフォーマンスの問題も軽減されます。

class Program
{
    static void Main(string[] args)
    {
        StringReader first = new StringReader("hello ");
        StringReader second = new StringReader("world");
        StringReader third = new StringReader("!");

        using (var allOfThem = first.Concat(second).Concat(third))
        {
            //writes "hello world!"
            Console.WriteLine(allOfThem.ReadToEnd());
        }
        Console.Read();
    }
}

public static class Extensions
{
    public static TextReader Concat(this TextReader first, TextReader second)
    {
        return new ChainedTextReader(first, second);
    }

    private class ChainedTextReader : TextReader
    {
        private TextReader first;
        private TextReader second;
        private bool readFirst = true;

        public ChainedTextReader(TextReader first, TextReader second)
        {
            this.first = first;
            this.second = second;
        }

        public override int Peek()
        {
            if (readFirst)
            {
                return first.Peek();
            }
            else
            {
                return second.Peek();
            }
        }

        public override int Read()
        {
            if (readFirst)
            {
                int value = first.Read();
                if (value == -1)
                {
                    readFirst = false;
                }
                else
                {
                    return value;
                }
            }
            return second.Read();
        }

        public override void Close()
        {
            first.Close();
            second.Close();
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (disposing)
            {
                first.Dispose();
                second.Dispose();
            }
        }
    }
}
于 2010-05-27T23:25:42.610 に答える