Samstag, Januar 18, 2020

Effiziente Möglichkeit zum löschen einer Zeile aus einer text-Datei

Wie lösche ich eine bestimmte Zeile aus einer text-Datei. Was ist der effizienteste Weg, dies zu tun? Die Datei kann potenziell große(über Millionen Datensätze).

UPDATE:
unten ist der code den ich derzeit benutze, aber ich bin mir nicht sicher, ob es gut ist.

internal void DeleteMarkedEntries() {
    string tempPath=Path.GetTempFileName();
    using (var reader = new StreamReader(logPath)) {
        using (var writer = new StreamWriter(File.OpenWrite(tempPath))) {
            int counter = 0;
            while (!reader.EndOfStream) {
                if (!_deletedLines.Contains(counter)) {
                    writer.WriteLine(reader.ReadLine());
                }
                ++counter;
            }
        }
    }
    if (File.Exists(tempPath)) {
        File.Delete(logPath);
        File.Move(tempPath, logPath);
    }
}
  • Wenn du so große Daten speichern, warum bist du nicht mit einer „echten“ Datenbank? Ist es eine Einschränkung in dem, was Werkzeuge, die Sie zur Verfügung haben, Ihre aktuellen Fähigkeiten oder den Spezifikationen Ihres Projekts?
  • Es ist eine Anforderung, die von ‚oben‘. Mit echte Datenbank wäre einfacher für mich, aber leider kann ich es nicht verwenden.
  • Es ist nicht gut, es ist ein bug – sorry 🙁 – Siehe meine Antwort unten
InformationsquelleAutor Valentin | 2009-02-10

8 Kommentare

  1. 10

    Den naheliegendsten Weg, dies zu tun ist wahrscheinlich das beste, schreiben der gesamten Datei in eine neue Datei schreiben alle Zeilen außer die mit einem(s) Sie nicht wollen.

    Alternativ öffnen Sie die Datei für den wahlfreien Zugriff.

    Lesen bis zu dem Punkt, wo Sie wollen, um „löschen“ die Zeile.
    Überspringen Sie die Zeile zu löschen, und gelesen, dass die Anzahl von bytes (einschließlich der CR + LF – wenn es nötig ist), schreiben Sie, dass die Anzahl der bytes in der Zeile gelöscht, vorher beide Orte durch, die Anzahl der bytes und wiederholen Sie bis zum Ende der Datei.

    Hoffe, das hilft.

    BEARBEITEN – Jetzt, wo ich den code sehen

    if (!_deletedLines.Contains(counter)) 
    {                            
        writer.WriteLine(reader.ReadLine());                        
    }

    Wird nicht funktionieren, wenn Ihr die Linie, die Sie nicht wollen, Sie wollen immer noch, es zu Lesen, nicht nur zu schreiben es. Der obige code weder Lesen oder schreiben. Die neue Datei wird genau das gleiche wie die alte.

    Du willst so etwas wie

    string line = reader.ReadLine();
    if (!_deletedLines.Contains(counter)) 
    {                            
        writer.WriteLine(line);                        
    }
    • Danke für den Hinweis auf diesen Fehler
  2. 3

    Text-Dateien werden sequenziell, also, wenn Sie löschen eine Zeile, Sie müssen verschieben alle folgenden Zeilen bis.
    Sie können mit “ Datei-Zuordnung (eine win32-api, die Sie aufrufen können über PInvoke), um diesen Vorgang ein bisschen weniger schmerzhaft, aber Sie surelly sollte considere eine nicht sequenzielle Struktur, die für Sie Datei, so dass Sie markieren können, eine Zeile als gelöscht, ohne wirklich es zu entfernen aus der Datei… vor Allem, wenn es passieren sollte frenquently.

    Wenn ich mich erinnere Datei-Mapping-Api Hinzugefügt werden soll .Net 4.

  3. 2
         try{
         Scanner reader = new Scanner(new File("D:/seenu.txt")); 
         System.out.println("Enter serial number:");
         String sl1=bufRead.readLine();
         System.out.print("Please Enter The ServerName:");
         String name=bufRead.readLine();
         System.out.println("Please Enter The IPAddress");
         String ipa=bufRead.readLine();
    
        System.out.println("Line Deleted.");
         PrintWriter writer = new PrintWriter(new FileWriter(new File("D:/user.txt")),true); 
         //for(int w=0; w<n; w++)
           writer.write(reader.nextLine()); 
         reader.nextLine(); 
         while(reader.hasNextLine())
           writer.write(reader.nextLine());
         } catch(Exception e){
           System.err.println("Enjoy the stack trace!");
           e.printStackTrace();
         }
    • Ihre Antwort könnte verbessert werden durch eine kurze Beschreibung von dem, was Ihr Programm macht, unterscheidet sich von dem Kodex in der Frage.
  4. 0

    Wenn Sie absolut haben Verwendung eines text-Datei und kann nicht geändert werden, um eine Datenbank, möchten Sie vielleicht zu benennen, das seltsame symbol am Anfang einer Zeile bedeutet „line deleted“. Gerade haben Sie Ihren parser ignoriert diese Zeilen, wie Kommentar-Zeilen in die config-Dateien etc.

    Dann regelmäßig ein „compact“ – routine, wie Outlook, und die meisten Datenbank-Systeme, die re-schreibt die ganze Datei ohne die gelöschten Zeilen.

    Würde ich dringend gehen mit dem Denken, Vor der Codierung, die Antwort die Empfehlung einer Datenbank oder anderen strukturierten Datei.

    • ja, die Voraussetzung ist, um in der Lage sein, eine lesbare Datei (bin mir aber nicht sicher, wie Sie jedem Menschen möglich, durch überfliegen einer million Zeilen!). Ich kann nichts über diese Anforderung.
  5. 0

    Je nachdem, was genau zählt als „löschen“, Ihre beste Lösung sein mag, überschreiben Sie die betreffende Zeile mit Leerzeichen. Für viele Zwecke (einschließlich menschlichen Verzehr), dies entspricht dem löschen der Zeile völlig. Wenn die resultierende leere Zeile ist ein problem, und Sie sind sicher, Sie nie löschen Sie die erste Zeile, die Sie anfügen können, werden die Leerzeichen der vorherigen Zeile auch überschreiben CRLF mit zwei Räumen.

    (Basierend auf dem Kommentar von Bork Blatt Antwort)

  6. 0

    In meinem blog, habe ich ein Benchmark verschiedener I/O-Methoden von C#, um zu bestimmen, die effizientesten Weise zu tun, Datei-I/O. Im Allgemeinen sind Sie besser dran, unter Verwendung der Windows-ReadFile und WriteFile Funktionen. Der nächste Schnellste Weg, um Dateien Lesen in ist durch FileStream. Gute Leistung, Lesen Sie die Dateien in Blöcken zu einer Zeit statt von einer Linie zu einer Zeit, und dann tun Sie Ihre eigene Analyse. Der code, den Sie herunterladen können, von meinem blog gibt Sie ein Beispiel, wie dies zu tun. Es gibt auch eine C# – Klasse, kapselt den Windows-ReadFile /WriteFile Funktionen und ist Recht einfach zu bedienen. Siehe mein blog für weitere details an:

    http://designingefficientsoftware.wordpress.com/2011/03/03/efficient-file-io-from-csharp

    Bob Bryan MCSD

  7. -1

    Lesen die Datei in ein Wörterbuch nicht löschen von Zeilen setzen Sie die int auf 0
    auf der Linie müssen Sie markieren als gelöscht gesetzt int in 1. Verwenden Sie ein KeyValuePair zu extrahieren
    Zeilen, die nicht benötigt werden gelöscht, und schreiben Sie Sie in eine neue Datei.

    Dictionary<string, int> output = new Dictionary<string, int>();
    
    //read line from file
    
    ...
    
    //if need to delete line then set int value to 1
    
    //otherwise set int value to 0
    if (deleteLine)
    {
        output[line] = 1;
    }
    else
    {
        output[line] = 0;
    }
    
    //define the no delete List
    List<string> nonDeleteList = new List<string>();
    
    //use foreach to loop through each item in nonDeleteList and add each key
    //who's value is equal to zero (0) to the nonDeleteList.
    foreach (KeyValuePair<string, int> kvp in output)
    {
    
        if (kvp.Value == 0)
    
        {
    
            nonDeleteList.Add(kvp.Key);
    
        }
    }
    
    //write the nondeletelist to the output file
    File.WriteAllLines("OUTPUT_FILE_NAME", nonDeleteList.ToArray());

    Das ist es.

    • Mit einem Wörterbuch, ist überhaupt kein effizienter Weg.

Kostenlose Online-Tests