Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
600 views
in Technique[技术] by (71.8m points)

c# - How to string multiple TextReaders together?

I have 3 TextReaders -- a combination of StreamReaders and StringReaders. Conceptually, the concatenation of them is a single text document.

I want to call a method (not under my control) that takes a single TextReader. Is there any built-in or easy way to make a concatenating TextReader from multiple TextReaders?

(I could write my own TextReader subclass, but it looks like a fair amount of work. In that case, I'd just write them all out to a temp file and then open it with a single StreamReader.)

Is there an easy solution to this that I'm missing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I just threw this together, so it's not super-robust (no error handling, etc) but the basic test case works.

It works by creating an extension method for TextReader's which take a second, and returns a new TextReader class which internally calls Read() on the first until it runs out, and then starts calling Read()on the second. You can chain this indefinitely.

To provide a complete implementation of TextReader you only need to implement Read(), Peek(), Close() and Dispose(). All the other methods rely on specific implementation Read() to work. So creating your own TextReader really isn't so bad, as you can see below.

This also alleviates any performance concerns since we are simply wrapping the existing TextReaders and not actually invoking them to perform the concatenation.

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();
            }
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...