Stellen Sie StreamReader auf den Anfang zurück

74

Ich lese eine Datei zeilenweise und möchte den Lesevorgang durch Aufrufen einer Methode neu starten können Rewind().

Wie kann ich meine System.IO.StreamReaderund / oder die zugrunde liegende System.IO.FileStreamDatei manipulieren , um mit dem Lesen der Datei zu beginnen?

Ich hatte die clevere Idee, FileStream.Seek(long, SeekOffset)mich in der Datei zu bewegen, aber das Einschließen hat keine Auswirkung System.IO.StreamReader. Ich könnte Close()sowohl den Stream als auch die Leserreferenzen neu zuweisen, aber ich hoffe, es gibt einen besseren Weg.

Chris
quelle

Antworten:

121

Sie müssen sich auf den Stream zu suchen, wie Sie haben, dann rufen Sie DiscardBufferedDataauf der StreamReader. Dokumentation hier :

Bearbeiten: Codebeispiel hinzufügen:

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
Amy
quelle
5
Seien Sie vorsichtig, wenn Sie dies für Dateien tun, die keine einfachen ANSI-Textdateien sind (oder vielmehr für Dateien, die eine Codierungsvorverstärkung haben). Siehe meine Antwort unten für weitere Details.
Eamon
Sie vergessen die using-Klausel / das IDisposable-Muster. Neu in .NET 4.0 ist StreamReader (Stream, Encoding.UTF8, true, 1024, true) und der neue StreamWriter (Stream, Encoding.UTF8, 1024, true) überwinden das fehlerhafte IDisposable-Muster (das Schließen von StreamReader / Writer schließt den zugrunde liegenden Stream ... Selbst M $ macht es zumindest am Anfang nicht immer richtig. Wenn Sie mehr als einmal aus einem Stream lesen müssen, müssen Sie zwei oder mehr StreamReader verwenden, die jeweils eigene Klauseln verwenden (nicht ineinander verschachtelt). Ebenso mit StreamWriter. Es sollte sehr selten vorkommen, dass Sie DiscardBufferedData gemäß Dokumentation aufrufen.
TamusJRoyce
47

Ich benutze diese Methode:

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

Amys Antwort funktioniert bei einigen Dateien, aber abhängig von der Codierung des zugrunde liegenden Streams erhalten Sie möglicherweise unerwartete Ergebnisse.

Wenn der Stream beispielsweise UTF-8 ist und eine Präambel hat, verwendet der StreamReader diese, um die Codierung zu erkennen, und schaltet dann einige interne Flags aus, die ihn anweisen, die Codierung zu erkennen und die Präambel zu überprüfen. Wenn Sie die Position des Streams auf den Anfang zurücksetzen, verwendet der Stream-Reader die Präambel jetzt wieder, nimmt sie jedoch beim zweiten Mal in die Ausgabe auf. Es gibt keine öffentlichen Methoden zum Zurücksetzen dieses Codierungs- und Präambelstatus. Wenn Sie einen Stream-Reader "zurückspulen" müssen, ist es am sichersten, den zugrunde liegenden Stream wie gezeigt an den Anfang zu suchen (oder die Position festzulegen) und einen neuen StreamReader zu erstellen. Es reicht nicht aus, nur DiscardBufferedData () im StreamReader aufzurufen.

Eamon
quelle
18

Dies ist alles gut, wenn die Eigenschaft BaseStreamtatsächlich Positionauf 0 gesetzt werden kann.

Wenn Sie dies nicht können (Beispiel wäre ein HttpWebResponseStream), ist es eine gute Option, den Stream in einen MemoryStream... zu kopieren. Dort können Sie Positionauf 0 setzen und den Stream Streamso oft neu starten, wie Sie möchten.

TheBoyan
quelle
1
Wie kopiere ich den Stream in einen Speicher-Stream?
Knocte
OH Ich muss die Antwort auf Poistion 0 zurücksetzen und neu starten, aber wie?
PKCS12
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;
   }
}
vyv
quelle
5
Bitte geben Sie einige Informationen an, warum dieses Codefragment das in der Frage beschriebene Problem löst.
Stephen Reindl
0

Die Frage ist nach einer StreamReader.Rewind()Methode. Sie suchen, StreamReader.BaseStream.Position = 0;was den Leser zum Anfang zurücksetzt, damit er wieder gelesen werden kann.

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());
}
Md Shahriar
quelle
Das hat bei mir nicht gut funktioniert. Die eingelesene HTML-Datei wurde zweimal angezeigt, nachdem die erste Zeile gelesen wurde, und dann wurde der vorgeschlagene Reset verwendet. Vielleicht funktioniert es in einigen Fällen, aber nicht in meinen.
JohnH
1
Funktioniert gut, wenn ich sr.BaseStream.Position = 0 verwende; sr.DiscardBufferedData ();
Chashitsu
0
public static void removeDuplicatedLinesBigFile2(string inFile, string outFile)
{
    int counter1 = 0, counter2 = 0;
    string line1, line2;
    bool band = false;

    // Read the file and display it line by line.  
    System.IO.StreamReader fileIN1 = new System.IO.StreamReader(inFile);
    System.IO.StreamReader fileIN2 = new System.IO.StreamReader(inFile);
    System.IO.StreamWriter fileOut = new System.IO.StreamWriter(outFile);

    while ((line1 = fileIN1.ReadLine()) != null)
    {
        //band = false;
        int counter = 0;
        fileIN2.BaseStream.Position = 0;
        fileIN2.DiscardBufferedData();

        while ((line2 = fileIN2.ReadLine()) != null)
        {                   
            if (line1.Equals(line2))
                counter++;

            if (counter > 1)
                break;
        }

        fileOut.WriteLine(line1);
        counter1++;
    }

    fileIN1.Close();
    fileIN2.Close();
    Console.WriteLine("Total Text Rows Copied: {0}", counter1);
}
Mauricio Kenny
quelle
Mit dieser Methode können Sie eine Textdatei verarbeiten, um eine neue zu erstellen, und das Kopieren wiederholter Textzeilen stornieren. Hier ist ein Beispiel für die Verwendung von DiscardBufferedData () nach BaseStream.Position = 0;
Mauricio Kenny