Как представить несколько TextReaders в виде строки вместе?

У меня есть 3 TextReaders - комбинация StreamReaders и StringReaders. Концептуально, конкатенация их является единственным текстовым документом.

Я хочу назвать метод (не под моим управлением), который берет единственный TextReader. Есть ли какой-либо встроенный или простой способ сделать конкатенирующий TextReader из нескольких TextReaders?

мог записать свой собственный подкласс TextReader, но он похож на изрядный объем работы. В этом случае я просто записал бы им всем во временный файл и затем открыл бы его с единственным StreamReader.)

Существует ли легкое решение этого, что я отсутствую?

5
задан Ken 27 May 2010 в 23:09
поделиться

1 ответ

Я просто собрал это вместе, так что это не очень надежно (нет обработки ошибок и т.д.), но основной тестовый пример работает.

Он работает путем создания метода расширения для TextReader, который занимает секунду, и возвращает новый класс TextReader, который внутренне вызывает Read() на первом, пока он не закончится, а затем начинает вызывать Read()на втором. Вы можете повторять эту цепочку бесконечно.

Для полной реализации 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();
            }
        }
    }
}
5
ответ дан 14 December 2019 в 19:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: