Как сбросить курсор C # .NET TextReader обратно в начальную точку? - PullRequest
24 голосов
/ 06 мая 2009

У меня есть метод, который принимает экземпляр StringReader (чтение из буфера обмена) или экземпляр StreamReader (чтение из файла) и в настоящее время преобразует один из них как экземпляр TextReader.

Мне нужно, чтобы он «предварительно прочитал» часть исходного ввода, а затем вернул курсор в начало. У меня не обязательно есть оригинальное имя файла. Как мне это сделать?

Существует упоминание о методе Seek для System.IO.Stream, но он не реализован в TextReader, хотя он используется в StreamReader через свойство Basestream. Однако StringReader не имеет BaseStream свойства

Ответы [ 4 ]

37 голосов
/ 06 мая 2009

Это зависит от TextReader. Если это StreamReader, вы можете использовать:

sr.BaseStream.Position = 0;
sr.DiscardBufferedData();

(Предполагается, что основной поток доступен для поиска.)

Другие реализации TextReader могут не иметь концепцию «перемотки», так же, как IEnumerable<T>. Во многих отношениях вы можете думать о TextReader как о прославленном IEnumerable<char>. У него есть методы для чтения целых кусков данных за раз, чтения строк и т. Д., Но по сути это тип «прямого чтения».

РЕДАКТИРОВАТЬ: Я не верю, что StringReader поддерживает любой вид перемотки - вам будет лучше воссоздать StringReader из исходной строки, если вы можете. Если это невозможно, вы всегда можете создать свой собственный класс TextReader, который передает все «обычные» вызовы другому StringReader, но при необходимости воссоздает этот экземпляр прокси.

10 голосов
/ 06 мая 2009

Если это StreamReader и , если этот поток поддерживает поиск, то:

        reader.BaseStream.Seek(0, SeekOrigin.Begin);
        reader.DiscardBufferedData();

Однако это невозможно на произвольных TextReader с. Возможно, вы могли бы прочитать все это как строку, тогда вы можете использовать StringReader несколько раз?

3 голосов
/ 04 мая 2012

Я наткнулся на ваш пост и был довольно разочарован тем, что это невозможно. Я быстро взломал что-то, что работает: просто избегайте чтения строк:

Stream stream = new MemoryStream((new System.Text.ASCIIEncoding().GetBytes(mystring)), false);
reader = new StreamReader(stream, new System.Text.ASCIIEncoding());

Это не красиво, и в нем используется ASCII (что мне и было нужно). Обратите внимание, что с другой кодировкой это не будет работать, так как вы будете искать n-й байт, который не равен n-му символу. Если вам это нужно, вы можете сделать что-то вроде

Stream stream = new MemoryStream((new System.Text.UTF32Encoding().GetBytes(mystring)), false);
reader = new StreamReader(stream, new System.Text.UTF32Encoding());

, поскольку UTF32 является единственным форматом Unicode фиксированной длины.

Теперь вы можете сделать

reader.BaseStream.Position = wherever; // or wherever * 4 for the UTF32 variety,
                                       // in your case, the beginning of the string,
                                       // which is always 0 obviously
reader.DiscardBufferedData();
0 голосов
/ 06 мая 2009

Ищите, и вы найдете.

Seek(0, SeekOrigin.Begin);

TextReader является производным от StreamReader. StreamReader содержит BaseStream свойство

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...