2016-02-10 16 views
8

Ich habe ein einfaches Programm, um eine Datei mit dem StreamReader zu lesen und Zeile für Zeile zu verarbeiten. Aber die Datei, die ich gerade lese, kann sich manchmal in einem Netzwerkordner befinden. Ich bin beim Testen mit einer solchen Datei gestolpert. Wenn die Netzwerkverbindung irgendwann während des Lesens verloren geht, bleibt sie in der gleichen Zeile und wiederholt sich in einer Endlosschleife, indem dieselbe Zeile wie das Ergebnis ausgegeben wird aus dem Stream.ReadLine().StreamReader.ReadLine hängt in einer Endlosschleife

Gibt es eine Möglichkeit, die ich finde, wenn das FileHandle nicht aus dem Stream selbst verfügbar ist? Ich habe erwartet, dass eine FileNotAvailableException-Art einer Ausnahme ausgelöst wird, wenn das Dateihandle vom StreamReader verloren geht.

Hier ist mein Code-Schnipsel ...

 string file = @"Z://1601120903.csv"; //Network file 
     string line; 
     StringBuilder stb = new StringBuilder();  
     StreamReader stream = new StreamReader(file, Encoding.UTF8, true, 1048576); 
     do 
     { 
      line = stream.ReadLine(); 
      // Do some work here 
     } while (line != ""); 
+3

StreamReader kann den Griff nicht "verlieren". Wenn es in der Tat nicht zwischengespeicherte Daten verwenden kann und das Netzwerk zum Abrufen von Dateiinhalten treffen muss, schlägt der zugrunde liegende ReadFile() - Aufruf fehl, und Sie erhalten eine System.IOException. Welche Berichte "Netzwerkfehler", einer der vielen Dinge, die beim Lesen von Dateien schief gehen können. Sie würden die Ausnahme abfangen und den Benutzer darüber informieren, damit er alles Notwendige tun kann, um das Problem zu beheben. –

+1

Ich überlege, ob ich das hier schließen soll, weil hier ein Bug ist, der in diesem Code nicht sichtbar ist. Der hier gezeigte Code muss eine vereinfachte Version des echten Codes sein. – usr

+0

@HansPassant, ja ich dachte auch gleich das Gleiche. Aber wenn Sie diese Codezeile ausführen, wird das Problem auftreten. Es gibt keine Ausnahme, da es mich immer wieder auf die selbe Linie wirft. – Asanka

Antwort

7
+0

Ich habe diese beiden Eigenschaften überprüft. Nachdem das Dateihandle aufgrund von Netzwerkproblemen gelöscht wurde, geben beide Bedingungen true und stream zurück. ReadLine() gibt dieselbe Zeile immer wieder an die variable Zeile aus. – Asanka

+0

@Asanka Ich habe meine Antworten mit einigen Ergebnissen aus der Praxis aktualisiert. – DmitryG

+0

Seltsam. Es hat mir keine Ausnahme gemacht. Haben Sie die Verbindung unterbrochen, während Sie sich in der Mitte des Dateilesevorgangs befinden? – Asanka

17

Vergleich mit null nicht mit leeren String:

https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline(v=vs.110).aspx

Rückgabewert Typ: System.String Die nächste Zeile aus der Eingabestrom oder null, wenn das Ende des Eingabestreams erreicht ist.

do 
    { 
     line = stream.ReadLine(); 
     // Do some work here 
    } while (line != null); 

Ein besserer Ansatz ist jedoch .Net die Arbeit tun zu lassen (Linie durch Datei-Lesezeile) für Sie und fallen alle Leser:

foreach (String line in File.ReadLines(file)) { 
    // Do some work here 
    } 
+1

würde es Code verbessern, um etwas wie "string.IsNullOrEmpty (line)" zu verwenden? – terbubbs

+4

@terbubbs: nein, eine * leere Zeichenfolge * kann gut in der Mitte der Datei erscheinen –

+0

Aber das Problem ist nicht mit der Überprüfung von null oder leer. Nachdem das Dateihandle aufgrund von Netzwerkproblemen gelöscht wurde, gibt stream.ReadLine() dieselbe Zeile immer wieder an eine variable Zeile aus. Es wird nie leer oder null sein – Asanka

0

die Datei Unter der Annahme, sollte nicht ändern Sie es, während Sie es lesen, und es ist nicht riesig, möchten Sie vielleicht in Erwägung ziehen, es in eine temporäre Datei (lokal) zu kopieren und dann ohne Störung zu arbeiten.

Wenn Sie Index des Orts, um Sie dabei helfen zu erreichen könnte: 1

while ((line = sr.ReadLine()) != null) 
{ 
    Console.WriteLine(line); 
} 

Source

+0

Das lokale Kopieren der Datei scheint eine gute Lösung zu sein. Aber es kann eine Möglichkeit geben, dass die Datei selbst ziemlich groß ist. – Asanka

+1

Das behebt das Problem nicht, das er hat. Er geht fälschlicherweise davon aus, dass dieselbe Zeile wiederholt ausgegeben wird. Stattdessen ist dies ein Fehler mit seinem Code. – usr

+0

@Asanka wie ich gesagt habe, überprüfen Sie, ob das Kopieren einer Datei möglich ist, und wenn Sie immer noch den aktuellen Leserindex verfolgen möchten, sollten Sie die Lösung verwenden, die ich hinzugefügt habe. –

3

Wenn Sie es mit einem while -loop schreiben (EndOfStream):

using(StreamReader sr = new StreamReader(...)) { 
    while(!sr.EndOfStream) { 
     string line = sr.ReadLine(); 
     Console.WriteLine(line); 
    } 
} 

richtiger Ansatz 2 (Peek)

using(StreamReader sr = new StreamReader(...)) { 
    while(sr.Peek() >= 0) { 
     string line = sr.ReadLine(); 
    } 
} 

Hinweis: dass es um Bedrohung eine leere Zeichenkette als Ende der Datei nicht korrekt ist.

, wenn die Netzwerkverbindung zu einem bestimmten Zeitpunkt verloren, während ich lese, es wird in der gleichen Linie bleibt immer wieder in einer unendlichen Schleife Looping durch die gleiche Zeile wie das Ergebnis von stream.ReadLine resultierenden ()

Ich habe dieses Szenario gerade überprüft - die System.IO.IOException ("Der Netzwerkpfad wurde nicht gefunden."} Sollte in diesem Fall geworfen werden.

Wenn ich das mit einem try catch block umbringe, wird das mein Problem nicht beheben, oder?

In diesem Fall können Sie das Lesen brechen kann wie folgt dar:

string line; 
do { 
    try { 
     line = sr.ReadLine(); 
     // Do some work here 
    } 
    catch(System.IO.IOException) { 
     break; 
    } 
} while(line != null); 
1

Eine Möglichkeit File.ReadAllLines nutzen würde mehr() und es wird Datei und liest alle Zeilen und closig kümmern Öffnung die Datei und möglicherweise auch Szenario, wenn die Netzwerkverbindung verloren geht.

var lines = File.ReadAllLines("Z://1601120903.csv"); 

foreach(line in lines) 
{ 
// Do some work 
}