¿Cómo se restablece un C#.NET TextReader cursor volver al punto de inicio?


Tengo un método que toma una instancia StringReader (leyendo desde el portapapeles) o una instancia StreamReader (leyendo desde un archivo) y, en la actualidad, proyecta cualquiera de ellas como una instancia TextReader.

Lo necesito para 'pre-leer' parte de la entrada de origen, luego restablecer el cursor al inicio. No tengo necesariamente el nombre de archivo original. ¿Cómo hago esto?

Se menciona el método Seek de System.IO.Stream pero esto no se implementa en TextReader, aunque está en StreamReader a través del Basestream propiedad. Sin embargo StringReader no tiene una propiedad BaseStream

 22
Author: Brendan, 2009-05-06

4 answers

Depende del TextReader. Si es un StreamReader, puedes usar:

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

(Suponiendo que el flujo subyacente es buscable, por supuesto.)

Otras implementaciones de TextReader no pueden tener un concepto de "rebobinar", de la misma manera que IEnumerable<T> no. En muchos sentidos puedes pensar en TextReader como un IEnumerable<char> glorificado. Tiene métodos para leer trozos enteros de datos a la vez, leer líneas, etc., pero es fundamentalmente un tipo de "lectura directa".

EDITAR: No creo que StringReader soporte cualquier tipo de rebobinado-sería mejor recrear el StringReader de la cadena original, si puede. Si eso no es factible, siempre puede crear su propia clase TextReader que proxy todas las llamadas "normales" a otro StringReader, pero recrea esa instancia de proxy cuando es necesario.

 35
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-06 20:46:14

Si es un StreamReader, y si esa corriente soporta la búsqueda, entonces:

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

Sin embargo, esto no es posible en TextReaders arbitrarios. Tal vez podría leer todo como una cadena, entonces se puede utilizar StringReader repetidamente?

 10
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-25 11:47:19

Me encontré con su post, y estaba bastante decepcionado de que esto no es posible. Hackeé algo rápido que funciona: simplemente evita el stringreader por completo:

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

No es bonito, y utiliza ASCII (que era lo que necesitaba de todos modos). Tenga en cuenta que con una codificación diferente esto no funcionará, ya que buscará el n'ésimo byte que no tiene que ser igual al n'ésimo carácter. Si usted necesita que usted podría hacer algo como

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

Como UTF32 es el único unicode de longitud fija formato.

Ahora puedes hacer

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();
 3
Author: Martijn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-09 13:11:41

Buscad y hallaréis.

Seek(0, SeekOrigin.Begin);

TextReader se deriva de StreamReader. StreamReader contiene una propiedad BaseStream

 -3
Author: billb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-17 08:17:55