2009-05-06 9 views
21

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, arroja una instancia como TextReader.¿Cómo restablecer un cursor de C# .NET TextReader al punto de inicio?

lo necesito a 'pre-lectura' parte de la entrada de la fuente, a continuación, restablezca el cursor de nuevo al comienzo. No necesariamente tengo el nombre de archivo original. ¿Cómo hago esto?

Hay mención del método de System.IO.StreamSeek pero esto no está implementado en TextReader, aunque está en StreamReader través de la propiedad Basestream. Sin embargo, StringReader no tiene una propiedad BaseStream

Respuesta

34

Depende del TextReader. Si se trata de un StreamReader, puede utilizar:

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

(Suponiendo que la secuencia subyacente es reubicable, por supuesto.)

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

EDITAR: No creo que StringReader sea compatible con cualquier tipo de rebobinado; será mejor que recree el StringReader de la cadena original, si puede. Si eso no es factible, siempre puedes crear tu propia clase TextReader que proxies todas las llamadas "normales" a otra StringReader, pero recrea esa instancia proxy cuando lo necesita.

+1

Gracias por el aviso en BaseStream, he actualizado la pregunta para que tal vez el problema se pueda resolver por completo. – Brendan

+0

Gracias por eso, parece que tendré que volver a pensar qué se pasa al método usando una sobrecarga. – Brendan

+0

Tuve problemas al usar este tipo de reinicio: la cadena que se lee después de tal restablecimiento contiene 3 caracteres ocultos al principio que probablemente determinan la codificación. La consecuencia es que al comparar la lectura de cadena en el reinicio de secuencia de lectura y la "cadena esperada" sorprendentemente devuelve falso. – sthiers

-3

Busque y encontrará.

Seek(0, SeekOrigin.Begin); 

TextReader se deriva de StreamReader. StreamReader contiene una propiedad BaseStream

+1

"TextReader se deriva de StreamReader" - revés. –

+0

Sí, buen punto Marc. Esto contra el sentido común de la mayoría de la gente pero es verdad. – jpierson

10

Si se trata de un StreamReader, y si esa corriente soportes buscando, entonces:

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

Sin embargo, esto no es posible en arbitrarias TextReader s. ¿Quizás podría leer todo como una cadena, luego puede usar StringReader repetidamente?

+0

Gracias por el aviso en BaseStream, he actualizado la pregunta para que tal vez el problema se pueda resolver por completo. – Brendan

+0

Si inicializa su lector de texto de la siguiente manera: Lector TextReader = new StreamReader() entonces puede convertir el lector a la clase base y llamar al método después de buscar: stream.Seek (offset, SeekOrigin.Begin); (lector como StreamReader) .DiscardBufferedData(); – agrath

+0

@agrath por lo que dije sobre * arbitrario * 'TextReader's ... –

3

me encontré con su puesto, y era bastante diappointed que esto no es posible. Pirateé algo rápido que funciona: simplemente evita la StringReader 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 carácter n-ésimo. Si es necesario que se podí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 formato Unicode de longitud fija.

Ahora usted puede 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(); 
+1

Estaba haciendo una búsqueda de" 32 Unicode seek C# streamreader "y usted golpea el clavo en la cabeza con ese segundo fragmento. +1 ... ¡Lo probaré! –

+1

Ahora solo necesito una versión de 32 bits de StringBuilder y StringBuilder para no tener que meterme con las parejas sustitutas. (Hmm, incluso eso no acaba de resolver el análisis de una mezcla de \ n y Windows \ r \ n nuevas líneas, estas últimas son molestamente similares a una pareja sustituta.) –

+0

sí, diviértete con eso;) Si necesitas buscar , tienes un poco de dolor, así que si puedes evitarlo, trabaja alrededor. Tan pronto como tengas cuerdas otra vez, vuelves a estar en paz mental, y los pares sustitutos se pueden dejar en el tipo de datos String que maneja toda la dificultad para ti, y buscar mucho en una secuencia es un olor de todos modos. Por lo que va, lo mejor que puedes hacer con esa IMO es omitirla/omitirla en cualquier análisis sintáctico. – Martijn

Cuestiones relacionadas