2010-01-12 30 views
53

Estoy leyendo un archivo en línea por línea y quiero poder reiniciar la lectura llamando a un método Rewind().Volver StreamReader a Inicio

¿Cómo puedo manipular mi System.IO.StreamReader y/o su System.IO.FileStream subyacente para comenzar de nuevo con la lectura del archivo?

He tenido la ingeniosa idea de usar FileStream.Seek(long, SeekOffset) para mover el archivo, pero no tiene ningún efecto el System.IO.StreamReader adjunto. Pude Close() y reasignar tanto la transmisión como el lector, pero espero que haya una mejor manera.

Respuesta

93

Necesita buscar en la transmisión, como lo hizo, luego llame al DiscardBufferedData en el StreamReader. Documentación here:

Editar: Adición de código de ejemplo:

Stream s = new MemoryStream(); 
StreamReader sr = new StreamReader(s); 
// later... after we read stuff 
s.Position = 0; 
sr.DiscardBufferedData();  // reader now reading from position 0 
+4

tener cuidado al hacer esto en cualquier archivo que no son simples archivos de texto ANSI (o más bien los archivos que tengan una codificación Preámbulo). Ver mi respuesta a continuación para más detalles. – Eamon

+0

Olvidaste el uso de la cláusula/patrón de IDisposable. Nuevo en .NET 4.0 es StreamReader (stream, Encoding.UTF8, true, 1024, true) y el nuevo StreamWriter (stream, Encoding.UTF8, 1024, true) supera el patrón de IDisposable roto (al cerrar StreamReader/Writer se cierra la transmisión subyacente ... incluso M $ no siempre lo hace bien, al menos al principio). Si necesita leer de una secuencia más de una vez, tenga dos o más StreamReaders, cada uno en sus propias cláusulas de uso (no anidados dentro de la otra). Del mismo modo con StreamWriter. Debería ser muy raro que llame a DiscardBufferedData, según la documentación. – TamusJRoyce

16

Todo esto es bueno si el BaseStream realidad se puede establecer Position propiedad a 0.

Si no se puede (ejemplo podría ser una corriente HttpWebResponse) entonces una buena opción sería copiar la secuencia en un MemoryStream ... allí puede configurar Position en 0 y reiniciar el Stream tanto como desee.

14

La respuesta de Amy funcionará en algunos archivos, pero dependiendo de la codificación de la secuencia subyacente, puede obtener resultados inesperados.

Por ejemplo, si la transmisión es UTF-8 y tiene un preámbulo, StreamReader lo utilizará para detectar la codificación y luego desactivar algunos indicadores internos que le indican que detecte la codificación y verifique el preámbulo. Si restablece la posición del flujo hasta el comienzo, el lector de flujo ahora consumirá el preámbulo nuevamente, pero lo incluirá en el resultado la segunda vez. No hay métodos públicos para restablecer este estado de codificación y preámbulo así que lo más seguro que debe hacer si necesita "rebobinar" un lector de flujo es buscar el flujo subyacente al principio (o establecer la posición) como se muestra y crear un nuevo StreamReader. Simplemente llamando a DiscardBufferedData() en StreamReader no será suficiente.

19

que utiliza este método:

System.IO.StreamReader reader = new System.IO.StreamReader("file.txt") 
//end of reading 
reader.DiscardBufferedData(); 
reader.BaseStream.Seek(0, System.IO.SeekOrigin.Begin); 
-1

La cuestión está en busca de algún tipo de StreamReader.Rewind() método. Está buscando StreamReader.BaseStream.Position = 0; que restablece el lector para que pueda volver a leerse.

StreamReader sr = new StreamReader("H:/kate/rani.txt"); 

Console.WriteLine(sr.ReadToEnd()); 

sr.BaseStream.Position = 0; 

Console.WriteLine("----------------------------------"); 

while (!sr.EndOfStream) 
{ 
    Console.WriteLine(sr.ReadLine()); 
} 
+0

Esto no funcionó bien para mí. El archivo HTML que se está leyendo se muestra dos veces después de que se leyó la primera línea y luego se utilizó el restablecimiento sugerido. Tal vez funcione para algunos casos, pero no para el mío. – JohnH

1
public long ReadList(string fileName, Action<string> action,long position=0) 
{ 
    if (!File.Exists(fileName)) return 0; 

    using (var reader = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite),System.Text.Encoding.Unicode)) 
    { 
    if (position > 0)reader.BaseStream.Position = position; 

    while (!reader.EndOfStream) 
    { 
     action(reader.ReadLine()); 
    } 
    return reader.BaseStream.Position; 
    } 
} 
+3

Proporcione alguna información sobre por qué este fragmento de código resuelve el problema descrito en la pregunta. –

Cuestiones relacionadas