Textfile Linie löschen und währenddessen Zugriff sperren

tecla

Erfahrenes Mitglied
Hallo allerseits!

Ich habe ein txt-File indem eine Queue mit Aufgaben geführt wird. Das heisst mehrere Prozesse / Programminstanzen schreiben unten neue Linien hinein und die abarbeitende Instanz soll die oberste Linie lesen und diese anschliessend löschen.

Beim hinzufügen der Linien kann ich den exklusiven Zugriff auf dei Datei erreichen, indem ich beim FileStream FileShare.None setze. Ungefähr so:

Code:
           FileStream fs = null;
            bool bBesetzt = true;
            //10 Versuche, die XMLQueue.txt - Datei mit einer neuen Zeile zu ergänzen
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    //FileStream erstellen, Datei sperren
                    if (fs == null || fs.CanWrite == false)
                    {
                        if (File.Exists(sQueuePfad))
                        {
                            fs = new FileStream(sQueuePfad, FileMode.Append, FileAccess.Write, FileShare.None);
                        }
                        else
                        {
                            fs = new FileStream(sQueuePfad, FileMode.Create, FileAccess.Write, FileShare.None);
                        }
                    }
                    StreamWriter sw = new StreamWriter(fs, Encoding.Default);
                    sw.WriteLine(sXMLDatei);
                    sw.Flush();
                    sw.Close();
                    fs.Close();
                    bBesetzt = false;
                    break;
                }
                // 0,1 Sekunde warten, dann ist die Datei nachher vielleicht wieder frei
                catch  {  Thread.Sleep(100); }
            }

Aber beim Löschen einer Linie ist die Datei nicht gesperrt:


Code:
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    //Alle Zeilen lesen und ab Zeile 2 zum StringBuilder hinzufügen ...
                    int counter = 0;
                    StringBuilder sb = new StringBuilder();
                    // Zeile für Zeile in der Datei durchlaufen
                    //foreach (string sZeile in File.ReadLines(sQueuePfad, Encoding.Default))
                    foreach (string sZeile in File.ReadAllLines(sQueuePfad, Encoding.Default))
                    {
                        // ab Zeile 2 alles zum StringBuilder hinzufügen ...
                        if (counter == 0)
                            sXML2Read = sZeile;
                        else
                            sb.AppendLine(sZeile); // Zeile zum StringBuilder hinzufügen

                        counter++;
                    }

                    // mit Hilfe des StringBuilder Inhalts, die vorhandene Datei ersetzen
                    File.WriteAllText(sQueuePfad, sb.ToString(), Encoding.Default);
                    bBesetzt = false;
                    break;
                }
                catch { Thread.Sleep(100); }
            }

Im dümmsten Fall kann es also passieren, das der abarbeitende Prozess mit File.ReadAllLines die Datei einliest, nun gleichzeitig ein anderer Prozess eine Linie hinzufügt, die dann aber durch das File.WriteAllText wieder unabsichtlicherweise gelöscht wird.

Gibt es irgendeine Möglichkeit, das File auch beim Neuschreiben zu locken?


Herzlichen Dank für alle Ideen...
 
Hi.

Statt die Komfort-Methode ReadLines zu verwenden, erstelle einfach wie gehabt einen FileStream und sperre den Zugriff.

Dann führe die Verarbeitung durch.

Zum Schluß schreibe die Datei neu indem du an den Dateianfang springst (immer noch gelockt!) und die Daten neu reinschreibst.

Ungefähr so:
Code:
using (var fs = new FileStream(...)) {
    // read all lines

    // verarbeite

    // an den Anfang springen, Datei auf 0 stutzen
    fs.Seek(0, SeekOrigin.Begin);
    fs.SetLength(0);
    
    // write data
}
Gruß
 
Vielen Dank!
Das hat mich animiert, mich mal vertiefter mit dem Filestream auseinanderzusetzen!
Jetzt klappt alles bestens :)

Herzliche Grüsse
 
Zurück