Come trovare e sostituire il testo in un file con C #


157

Il mio codice finora

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

So come trovare il testo, ma non ho idea di come sostituire il testo nel file con il mio.


Considera questo commento solo come un suggerimento: se hai Visual Studio, puoi includere le cartelle nella soluzione e utilizzare la funzione di ricerca e sostituzione di Visual Studio
Buona

Risposte:


322

Leggi tutto il contenuto del file. Effettuare una sostituzione con String.Replace. Scrivi di nuovo il contenuto nel file.

string text = File.ReadAllText("test.txt");
text = text.Replace("some text", "new value");
File.WriteAllText("test.txt", text);

5
@WinCoder BTW per sostituzioni più complesse che puoi usareRegex.Replace
Sergey Berezovskiy,

35
Questo legge l'intero file in memoria contemporaneamente, non sempre così bene.
Banshee,

6
@Banshee Touche 'Ho appena provato a leggere 9.000.000 di righe e sono stato lanciato System out of memoryun'eccezione.
Squ1rr3lz,

4
Per file di grandi dimensioni è un problema più complesso. Leggi il byte byte, analizzalo, leggi un altro blocco, ecc.
Alexander

6
@Alexander Right. Un pezzo termina con "... som" e il successivo inizia con "e text ...". Lo rende un problema molto più complicato.
djv,

36

Farai fatica a scrivere sullo stesso file da cui stai leggendo. Un modo rapido è semplicemente fare questo:

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

Puoi spiegarlo meglio con

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

3
Questo è semplice ma non desiderabile per file di dimensioni molto grandi. (ps non sono io quello che ha effettuato il downgrade)
Alvin Wong il

3
Sono d'accordo, ma non puoi scrivere sul file mentre stai leggendo da esso. A meno che non si scriva in un altro file, quindi lo si sostituisca con una ridenominazione in seguito ... in entrambi i casi, il nuovo file deve essere archiviato altrove mentre lo si sta costruendo, sia in memoria che su disco.
Flynn1179,

@ Flynn1179 Non è vero in questo esempio. Funziona. Provalo. Immagino che ReadAllTextchiuda l'accesso ai file prima di WriteAllText. Uso questa tecnica nella mia app.
SteveCinq,

Lo so; questo esempio non scrive mentre sta leggendo, quello era il mio punto!
Flynn1179,

27

Devi scrivere tutte le righe che leggi nel file di output, anche se non le modifichi.

Qualcosa di simile a:

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);
  }
}

Se si desidera eseguire questa operazione sul posto, il modo più semplice è utilizzare un file di output temporaneo e alla fine sostituire il file di input con l'output.

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

(Cercare di eseguire operazioni di aggiornamento nel mezzo del file di testo è piuttosto difficile da ottenere correttamente perché avere sempre la sostituzione della stessa lunghezza è difficile dato che la maggior parte delle codifiche sono di larghezza variabile.)

EDIT: anziché due operazioni sui file per sostituire il file originale, meglio usarlo File.Replace("input.txt", "output.txt", null). (Vedi MSDN .)


1
VB ha dovuto cambiare 2 righe: utilizzando input come nuovo StreamReader (nome file) Mentre input.Peek ()> = 0
Brent

8

È probabile che dovrai inserire il file di testo in memoria e quindi eseguire le sostituzioni. Dovrai quindi sovrascrivere il file usando il metodo che conosci chiaramente. Quindi per prima cosa:

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

È quindi possibile scorrere e sostituire il testo nell'array.

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);
}

questo metodo ti dà un certo controllo sulle manipolazioni che puoi fare. Oppure, puoi semplicemente effettuare la sostituzione in una riga

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

Spero che aiuti.


6

Ecco come l'ho fatto con un file di grandi dimensioni (50 GB):

Ho provato 2 modi diversi: il primo, leggendo il file in memoria e usando Regex Replace o String Replace. Quindi ho aggiunto l'intera stringa a un file temporaneo.

Il primo metodo funziona bene per alcune sostituzioni Regex, ma Regex.Replace o String.Replace potrebbe causare errori di memoria insufficiente se si eseguono molte sostituzioni in un file di grandi dimensioni.

Il secondo è leggendo il file temporaneo riga per riga e costruendo manualmente ogni riga utilizzando StringBuilder e aggiungendo ciascuna riga elaborata al file dei risultati. Questo metodo è stato piuttosto veloce.

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();
    }

0

Questo codice ha funzionato per me

- //-------------------------------------------------------------------
                           // 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);
                           }

0

tendo a usare il semplice codice forward il più possibile, sotto il codice ha funzionato bene con me

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();
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.