2009-03-21 37 views
31

Ich habe ein Problem: Wie kann ich eine Zeile aus einer Textdatei in C# löschen?Wie lösche ich eine Zeile aus einer Textdatei in C#?

+0

Er/sie bedeutet, wie es programmgesteuert zu löschen ich denke. – splattne

+35

@John Saunders: Ist es so schwer zu verstehen, dass das OP eine Zeile aus einer Textdatei mit C# löschen möchte? Wie ist das nicht spezifisch? Lasst uns den Neulingen ein bisschen mehr entgegenkommen. –

Antwort

24

Die Datei lesen, die Zeile im Speicher löschen und den Inhalt in die Datei zurückspeichern (überschreiben). Wenn die Datei groß ist, möchten Sie sie Zeile für Zeile lesen und eine temporäre Datei erstellen, die später die ursprüngliche ersetzt.

17

Ich stimme mit John Saunders überein, das ist nicht wirklich C# spezifisch. Um jedoch Ihre Frage zu beantworten: Sie müssen die Datei grundsätzlich neu schreiben. Es gibt zwei Möglichkeiten, wie Sie dies tun können.

  • Lesen Sie die gesamte Datei in den Speicher (zB mit File.ReadAllLines)
  • die beanstandete Zeile entfernen (in diesem Fall ist es wahrscheinlich am einfachsten, die String-Array in eine List<string> dann entfernen Sie die Zeile konvertieren)
  • Schreiben Sie alle Rest der Rückseite (zB mit File.WriteAllLines) Linien - möglicherweise die List<string> in ein String-Array wieder ToArray

mit konvertieren das bedeutet, müssen Sie wissen, dass Sie genug Speicher haben obwohl. Eine Alternative:

  • öffnen sowohl die Input-Datei und eine neue Ausgabedatei (als TextReader/TextWriter, zB mit File.OpenText und File.CreateText)
  • eine Zeile lesen (TextReader.ReadLine) - wenn Sie nicht wollen, löschen es, schreiben Sie es in die Ausgabedatei (TextWriter.WriteLine)
  • wenn Sie alle Zeilen gelesen haben, schließen sowohl Leser und Schreiber (wenn Sie using Aussagen für beide verwenden, dies automatisch geschehen)
  • wenn Sie möchten, Um die Eingabe durch die Ausgabe zu ersetzen, löschen Sie e die Eingabedatei und verschieben Sie die Ausgabedatei an ihren Platz.
+0

Ich bin in der gleichen Situation, in der ich den Header einer Datei entfernen und in eine andere Datei anhängen muss. Unter Windows, wenn ich DOS-Funktionen über C# verwende, denken Sie, dass es ein Leistungsgewinn wäre? Hier ist der Befehl .. > MEHR +1 "sourcefilepath"> "targetFilePath" –

+0

@ ImranAmjad: Ich weiß es nicht, aber es klingt nicht wie es wäre schwer zu testen. Ist dies ein besonders performance-kritischer Teil Ihres Workflows? –

+0

Ja, Dateigröße kann mehr als eine halbe GB sein und ich muss es häufig tun. Die Ausführung von DOS-Befehlen nimmt die ganze Last und ich bin nur sicher, dass es schneller ist, da DOS-Befehle alle OS-Ebenen umgehen. Ich bin mir über viele Interna nicht sicher. Es speichert auch viele Zeilen Code, aber die Lesbarkeit des Codes ist für einige Personen kompromittiert. –

63

Für sehr große Dateien würde ich so etwas wie dieses

string tempFile = Path.GetTempFileName(); 

using(var sr = new StreamReader("file.txt")) 
using(var sw = new StreamWriter(tempFile)) 
{ 
    string line; 

    while((line = sr.ReadLine()) != null) 
    { 
     if(line != "removeme") 
      sw.WriteLine(line); 
    } 
} 

File.Delete("file.txt"); 
File.Move(tempFile, "file.txt"); 

aktualisieren tut ursprünglich ich diese wieder im Jahr 2009 schrieb, und ich dachte, dass es mit einem Update interessant sein könnte. Heute könnte man das erreichen oben mit LINQ and deferred execution

var tempFile = Path.GetTempFileName(); 
var linesToKeep = File.ReadLines(fileName).Where(l => l != "removeme"); 

File.WriteAllLines(tempFile, linesToKeep); 

File.Delete(fileName); 
File.Move(tempFile, fileName); 

Der obige Code ist fast genau das gleiche wie das erste Beispiel, das Lesen Zeile für Zeile und während eine minimale Menge an Daten im Speicher zu halten.

Ein Disclaimer könnte in Ordnung sein. Da wir hier über Textdateien sprechen, müssen Sie die Festplatte sehr selten als Zwischenspeichermedium verwenden. Wenn Sie nicht mit sehr großen Protokolldateien arbeiten, sollte es kein Problem sein, stattdessen den Inhalt in den Speicher zu lesen und die temporäre Datei zu umgehen.

File.WriteAllLines(fileName, 
    File.ReadLines(fileName).Where(l => l != "removeme").ToList()); 

Beachten Sie, dass die .ToList ist hier entscheidend sofortige Ausführung zu erzwingen. Beachten Sie auch, dass in allen Beispielen davon ausgegangen wird, dass die Textdateien UTF-8-codiert sind.

2

Ich würde sehr einfach:

  • Öffnen Sie die Datei für Schreib-/
  • Lesen/suchen durch sie bis zum Anfang der Zeile Sie
  • Stellen Sie den Schreibzeiger auf die zu löschenden schreiben Aktueller Lesezeiger
  • Lesen Sie bis zum Ende der Zeile, die wir löschen, und überspringen Sie die Zeilentrennzeichen (die Anzahl der Zeichen wird gezählt, wir nennen es nline)
  • Byteweise lesen und schreibe jedes Byte in die Datei
  • Wenn Sie fertig sind, schneiden Sie die Datei auf (orig_length - nline).
5

I verlängert, was Markus Olsson vorgeschlagen und kam mit dieser Klasse auf, die mehrere Suchzeichenfolgen und ein paar Ereignis fügt hinzu:

public static class TextLineRemover 
{ 
    public static void RemoveTextLines(IList<string> linesToRemove, string filename, string tempFilename) 
    { 
     // Initial values 
     int lineNumber = 0; 
     int linesRemoved = 0; 
     DateTime startTime = DateTime.Now; 

     // Read file 
     using (var sr = new StreamReader(filename)) 
     { 
      // Write new file 
      using (var sw = new StreamWriter(tempFilename)) 
      { 
       // Read lines 
       string line; 
       while ((line = sr.ReadLine()) != null) 
       { 
        lineNumber++; 
        // Look for text to remove 
        if (!ContainsString(line, linesToRemove)) 
        { 
         // Keep lines that does not match 
         sw.WriteLine(line); 
        } 
        else 
        { 
         // Ignore lines that DO match 
         linesRemoved++; 
         InvokeOnRemovedLine(new RemovedLineArgs { RemovedLine = line, RemovedLineNumber = lineNumber}); 
        } 
       } 
      } 
     } 
     // Delete original file 
     File.Delete(filename); 

     // ... and put the temp file in its place. 
     File.Move(tempFilename, filename); 

     // Final calculations 
     DateTime endTime = DateTime.Now; 
     InvokeOnFinished(new FinishedArgs {LinesRemoved = linesRemoved, TotalLines = lineNumber, TotalTime = endTime.Subtract(startTime)}); 
    } 

    private static bool ContainsString(string line, IEnumerable<string> linesToRemove) 
    { 
     foreach (var lineToRemove in linesToRemove) 
     { 
      if(line.Contains(lineToRemove)) 
       return true; 
     } 
     return false; 
    } 

    public static event RemovedLine OnRemovedLine; 
    public static event Finished OnFinished; 

    public static void InvokeOnFinished(FinishedArgs args) 
    { 
     Finished handler = OnFinished; 
     if (handler != null) handler(null, args); 
    } 

    public static void InvokeOnRemovedLine(RemovedLineArgs args) 
    { 
     RemovedLine handler = OnRemovedLine; 
     if (handler != null) handler(null, args); 
    } 
} 

public delegate void Finished(object sender, FinishedArgs args); 

public class FinishedArgs 
{ 
    public int TotalLines { get; set; } 
    public int LinesRemoved { get; set; } 
    public TimeSpan TotalTime { get; set; } 
} 

public delegate void RemovedLine(object sender, RemovedLineArgs args); 

public class RemovedLineArgs 
{ 
    public string RemovedLine { get; set; } 
    public int RemovedLineNumber { get; set; } 
} 

Verbrauch:

 TextLineRemover.OnRemovedLine += (o, removedLineArgs) => Console.WriteLine(string.Format("Removed \"{0}\" at line {1}", removedLineArgs.RemovedLine, removedLineArgs.RemovedLineNumber)); 
     TextLineRemover.OnFinished += (o, finishedArgs) => Console.WriteLine(string.Format("{0} of {1} lines removed. Time used: {2}", finishedArgs.LinesRemoved, finishedArgs.TotalLines, finishedArgs.TotalTime.ToString())); 
     TextLineRemover.RemoveTextLines(new List<string> { "aaa", "bbb" }, fileName, fileName + ".tmp"); 
5

So entfernen Sie Artikel aus Textdatei, verschieben Sie zuerst den gesamten Text in eine Liste und entfernen Sie das gewünschte Element. Dann schreibe den in der Liste gespeicherten Text in die Textdatei

List<string> quotelist=File.ReadAllLines(filename).ToList(); 
      string firstItem= quotelist[0]; 
      quotelist.RemoveAt(0); 
      File.WriteAllLines(filename, quotelist.ToArray()); 
      return firstItem; 
+1

Wie wäre es mit "der anderen Hälfte" (okay, die anderen 0,05 Prozent), die ReadAllLines() oder WriteAllLines() in ihrer Version von .NET nicht haben? –

2

Hallo Leute, ich habe eine Methode geschrieben, Zeilen aus Dateien zu löschen. Dieses Programm verwendet using System.IO

meinen Code Siehe:

void File_DeleteLine(int Line, string Path) 
    { 
     StringBuilder sb = new StringBuilder(); 
     using (StreamReader sr = new StreamReader(Path)) 
     { 
      int Countup = 0; 
      while (!sr.EndOfStream) 
      { 
       Countup++; 
       if (Countup != Line) 
       { 
        using (StringWriter sw = new StringWriter(sb)) 
        { 
         sw.WriteLine(sr.ReadLine()); 
        } 
       } 
       else 
       { 
        sr.ReadLine(); 
       } 
      } 
     } 
     using (StreamWriter sw = new StreamWriter(Path)) 
     { 
      sw.Write(sb.ToString()); 
     } 
    } 
0

Warum nicht diese verwenden kann? Erstellen Sie zunächst ein Array:

string[] lines = File.ReadAllLines(openFileDialog1.FileName); 

dann die Zeile, die Sie löschen müssen, suchen und ersetzen Sie es mit "":

lines[x].Replace(lines[x], ""); 

Fertig!

+1

Dies * entfernt nicht * die Zeile aus der Datei, es macht nur die Zeile 'x' leer. Wenn Sie also viel tun würden, würden Sie am Ende eine Menge leerer Returns in der Datei haben, was die Indizes durcheinander bringen könnte. – carefulnow1

Verwandte Themen