So finden und ersetzen Sie Text in einer Datei mit C #

157

Mein Code bisher

StreamReader reading = File.OpenText("test.txt");
string str;
while ((str = reading.ReadLine())!=null)
{
      if (str.Contains("some text"))
      {
          StreamWriter write = new StreamWriter("test.txt");
      }
}

Ich weiß, wie ich den Text finde, aber ich habe keine Ahnung, wie ich den Text in der Datei durch meinen eigenen ersetzen soll.

Gewinnen Sie Coder
quelle
Betrachten Sie diesen Kommentar nur als Tipp: Wenn Sie Visual Studio haben, können Sie die Ordner in die Lösung aufnehmen und die Such- und Ersetzungsfunktion von Visual Studio verwenden. Viel Glück
StackOrder
Mögliches Duplikat von Öffnen Sie eine Datei und ersetzen Sie Zeichenfolgen in C #
RecklessSergio

Antworten:

321

Lesen Sie den gesamten Dateiinhalt. Machen Sie einen Ersatz mit String.Replace. Schreiben Sie den Inhalt zurück in die Datei.

string text = File.ReadAllText("test.txt");
text = text.Replace("some text", "new value");
File.WriteAllText("test.txt", text);
Sergey Berezovskiy
quelle
5
@ WinCoder BTW für komplexere Ersetzungen, die Sie verwenden könnenRegex.Replace
Sergey Berezovskiy
35
Dadurch wird die gesamte Datei auf einmal in den Speicher gelesen, was nicht immer so gut ist.
Banshee
6
@Banshee Touche 'Ich habe gerade versucht, 9.000.000 Zeilen zu lesen und wurde eine System out of memoryAusnahme geworfen .
Squ1rr3lz
4
Bei großen Dateien ist das Problem komplexer. Lesen Sie den Byte-Block, analysieren Sie ihn, lesen Sie einen anderen Block usw.
Alexander
6
@ Alexander Richtig. Ein Block endet mit "... som" und der nächste beginnt mit "e text ...". Macht es zu einem viel komplizierteren Problem.
DJV
36

Es wird Ihnen schwer fallen, in dieselbe Datei zu schreiben, aus der Sie lesen. Ein schneller Weg ist, dies einfach zu tun:

File.WriteAllText("test.txt", File.ReadAllText("test.txt").Replace("some text","some other text"));

Mit dem können Sie das besser auslegen

string str = File.ReadAllText("test.txt");
str = str.Replace("some text","some other text");
File.WriteAllText("test.txt", str);
Flynn1179
quelle
3
Dies ist einfach, aber für sehr große Dateien nicht wünschenswert. (ps Ich bin nicht derjenige, der herabgestimmt hat)
Alvin Wong
3
Ich würde zustimmen, aber Sie können nicht in die Datei schreiben, während Sie daraus lesen. Sofern Sie nicht in eine andere Datei schreiben, ersetzen Sie diese anschließend durch eine Umbenennung. In beiden Fällen muss die neue Datei während der Erstellung an einem anderen Ort gespeichert werden, unabhängig davon, ob sie sich im Speicher oder auf der Festplatte befindet.
Flynn1179
@ Flynn1179 In diesem Beispiel nicht wahr. Es klappt. Versuch es. Ich denke, das ReadAllTextschließt den Dateizugriff vor WriteAllText. Ich benutze genau diese Technik in meiner eigenen App.
SteveCinq
Ich weiß; Dieses Beispiel schreibt nicht, während es liest, das war mein Punkt!
Flynn1179
27

Sie müssen alle Zeilen, die Sie gelesen haben, in die Ausgabedatei schreiben, auch wenn Sie sie nicht ändern.

Etwas wie:

using (var input = File.OpenText("input.txt"))
using (var output = new StreamWriter("output.txt")) {
  string line;
  while (null != (line = input.ReadLine())) {
     // optionally modify line.
     output.WriteLine(line);
  }
}

Wenn Sie diesen Vorgang an Ort und Stelle ausführen möchten, ist es am einfachsten, eine temporäre Ausgabedatei zu verwenden und am Ende die Eingabedatei durch die Ausgabe zu ersetzen.

File.Delete("input.txt");
File.Move("output.txt", "input.txt");

(Der Versuch, Aktualisierungsvorgänge in der Mitte einer Textdatei durchzuführen, ist ziemlich schwierig, da es schwierig ist, immer den gleichen Ersatz zu haben, da die meisten Codierungen eine variable Breite haben.)

BEARBEITEN: Anstatt zwei Dateivorgänge zum Ersetzen der Originaldatei zu verwenden, ist die Verwendung besser File.Replace("input.txt", "output.txt", null). (Siehe MSDN .)

Richard
quelle
1
VB musste 2 Zeilen ändern: Verwenden der Eingabe als neuer StreamReader (Dateiname) Während der Eingabe.Peek ()> = 0
Brent
8

Es ist wahrscheinlich, dass Sie die Textdatei in den Speicher ziehen und dann die Ersetzungen vornehmen müssen. Sie müssen die Datei dann mit der Methode überschreiben, die Sie genau kennen. Sie würden also zuerst:

// Read lines from source file.
string[] arr = File.ReadAllLines(file);

Sie können dann den Text im Array durchlaufen und ersetzen.

var writer = new StreamWriter(GetFileName(baseFolder, prefix, num));
for (int i = 0; i < arr.Length; i++)
{
    string line = arr[i];
    line.Replace("match", "new value");
    writer.WriteLine(line);
}

Mit dieser Methode können Sie die Manipulationen steuern, die Sie ausführen können. Oder Sie können das Ersetzen nur in einer Zeile durchführen

File.WriteAllText("test.txt", text.Replace("match", "new value"));

Ich hoffe das hilft.

Mond Ritter
quelle
6

So habe ich es mit einer großen Datei (50 GB) gemacht:

Ich habe zwei verschiedene Möglichkeiten ausprobiert: die erste, das Einlesen der Datei in den Speicher und die Verwendung von Regex Replace oder String Replace. Dann habe ich die gesamte Zeichenfolge an eine temporäre Datei angehängt.

Die erste Methode eignet sich gut für einige Regex-Ersetzungen, aber Regex.Replace oder String.Replace können zu Speicherfehlern führen, wenn Sie viele Ersetzungen in einer großen Datei durchführen.

Die zweite Möglichkeit besteht darin, die temporäre Datei Zeile für Zeile zu lesen und jede Zeile manuell mit StringBuilder zu erstellen und jede verarbeitete Zeile an die Ergebnisdatei anzuhängen. Diese Methode war ziemlich schnell.

static void ProcessLargeFile()
{
        if (File.Exists(outFileName)) File.Delete(outFileName);

        string text = File.ReadAllText(inputFileName, Encoding.UTF8);

        // EX 1 This opens entire file in memory and uses Replace and Regex Replace --> might cause out of memory error

        text = text.Replace("</text>", "");

        text = Regex.Replace(text, @"\<ref.*?\</ref\>", "");

        File.WriteAllText(outFileName, text);




        // EX 2 This reads file line by line 

        if (File.Exists(outFileName)) File.Delete(outFileName);

        using (var sw = new StreamWriter(outFileName))      
        using (var fs = File.OpenRead(inFileName))
        using (var sr = new StreamReader(fs, Encoding.UTF8)) //use UTF8 encoding or whatever encoding your file uses
        {
            string line, newLine;

            while ((line = sr.ReadLine()) != null)
            {
              //note: call your own replace function or use String.Replace here 
              newLine = Util.ReplaceDoubleBrackets(line);

              sw.WriteLine(newLine);
            }
        }
    }

    public static string ReplaceDoubleBrackets(string str)
    {
        //note: this replaces the first occurrence of a word delimited by [[ ]]

        //replace [[ with your own delimiter
        if (str.IndexOf("[[") < 0)
            return str;

        StringBuilder sb = new StringBuilder();

        //this part gets the string to replace, put this in a loop if more than one occurrence  per line.
        int posStart = str.IndexOf("[[");
        int posEnd = str.IndexOf("]]");
        int length = posEnd - posStart;


        // ... code to replace with newstr


        sb.Append(newstr);

        return sb.ToString();
    }
Live-Liebe
quelle
0

Dieser Code hat bei mir funktioniert

- //-------------------------------------------------------------------
                           // Create an instance of the Printer
                           IPrinter printer = new Printer();

                           //----------------------------------------------------------------------------
                           String path = @"" + file_browse_path.Text;
                         //  using (StreamReader sr = File.OpenText(path))

                           using (StreamReader sr = new System.IO.StreamReader(path))
                           {

                              string fileLocMove="";
                              string newpath = Path.GetDirectoryName(path);
                               fileLocMove = newpath + "\\" + "new.prn";



                                  string text = File.ReadAllText(path);
                                  text= text.Replace("<REF>", reference_code.Text);
                                  text=   text.Replace("<ORANGE>", orange_name.Text);
                                  text=   text.Replace("<SIZE>", size_name.Text);
                                  text=   text.Replace("<INVOICE>", invoiceName.Text);
                                  text=   text.Replace("<BINQTY>", binQty.Text);
                                  text = text.Replace("<DATED>", dateName.Text);

                                       File.WriteAllText(fileLocMove, text);



                               // Print the file
                               printer.PrintRawFile("Godex G500", fileLocMove, "n");
                              // File.WriteAllText("C:\\Users\\Gunjan\\Desktop\\new.prn", s);
                           }
Radhason Macht
quelle
0

Ich neige dazu, einfachen Vorwärtscode so oft wie möglich zu verwenden. Der folgende Code hat bei mir gut funktioniert

using System;
using System.IO;
using System.Text.RegularExpressions;

/// <summary>
/// Replaces text in a file.
/// </summary>
/// <param name="filePath">Path of the text file.</param>
/// <param name="searchText">Text to search for.</param>
/// <param name="replaceText">Text to replace the search text.</param>
static public void ReplaceInFile( string filePath, string searchText, string replaceText )
{
    StreamReader reader = new StreamReader( filePath );
    string content = reader.ReadToEnd();
    reader.Close();

    content = Regex.Replace( content, searchText, replaceText );

    StreamWriter writer = new StreamWriter( filePath );
    writer.Write( content );
    writer.Close();
}
Ali
quelle