Comment rechercher et remplacer du texte dans un fichier avec C #


157

Mon code jusqu'à présent

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

Je sais comment trouver le texte, mais je ne sais pas comment remplacer le texte du fichier par le mien.


Considérez ce commentaire comme une pointe seulement: Si vous avez Visual Studio, vous pouvez inclure les dossiers dans la solution et utiliser la recherche et remplacer du visual studio .best de chance
StackOrder

Réponses:


322

Lisez tout le contenu du fichier. Faites un remplacement avec String.Replace. Réécrivez le contenu dans le fichier.

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

5
@WinCoder BTW pour des remplacements plus complexes que vous pouvez utiliserRegex.Replace
Sergey Berezovskiy

35
Cela lit le fichier entier en mémoire à la fois, pas toujours aussi bien.
Banshee

6
@Banshee Touche «J'ai juste essayé de lire 9 000 000 de lignes et j'ai été une System out of memoryexception.
Squ1rr3lz

4
Pour les gros fichiers, c'est un problème plus complexe. Lire un morceau d'octet, les analyser, lire un autre morceau, etc.
Alexander

6
@Alexander C'est vrai. Un morceau se termine par "... som", et le suivant commence par "e text ...". Cela en fait un problème beaucoup plus compliqué.
djv

36

Vous allez avoir du mal à écrire dans le même fichier que vous lisez. Un moyen rapide consiste simplement à faire ceci:

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

Vous pouvez mieux exposer cela avec

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

3
Ceci est simple mais pas souhaitable pour les fichiers très volumineux. (ps je ne suis pas celui qui a voté contre)
Alvin Wong

3
Je suis d'accord, mais vous ne pouvez pas écrire dans le fichier pendant que vous le lisez. À moins que vous n'écriviez dans un autre fichier, puis que vous le remplaciez par un changement de nom par la suite .. de toute façon, le nouveau fichier doit être stocké ailleurs pendant que vous le construisez, que ce soit en mémoire ou sur disque.
Flynn1179

@ Flynn1179 Non vrai dans cet exemple. Ça marche. Essaye le. Je suppose que l' ReadAllTextaccès aux fichiers ferme avant WriteAllText. J'utilise cette technique même dans ma propre application.
SteveCinq

Je connais; cet exemple n'écrit pas pendant sa lecture, c'était mon point!
Flynn1179

27

Vous devez écrire toutes les lignes que vous lisez dans le fichier de sortie, même si vous ne les modifiez pas.

Quelque chose comme:

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

Si vous souhaitez effectuer cette opération sur place, le moyen le plus simple consiste à utiliser un fichier de sortie temporaire et à la fin de remplacer le fichier d'entrée par la sortie.

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

(Essayer d'effectuer des opérations de mise à jour au milieu d'un fichier texte est assez difficile à obtenir car il est difficile de toujours avoir le remplacement de la même longueur étant donné que la plupart des encodages sont de largeur variable.)

EDIT: Plutôt que deux opérations sur les fichiers pour remplacer le fichier d'origine, mieux vaut l'utiliser File.Replace("input.txt", "output.txt", null). (Voir MSDN .)


1
VB a dû changer 2 lignes: Utilisation de l'entrée comme nouveau StreamReader (nom de fichier) Alors que input.Peek ()> = 0
Brent

8

Il est probable que vous deviez extraire le fichier texte en mémoire, puis effectuer les remplacements. Vous devrez ensuite écraser le fichier en utilisant la méthode que vous connaissez clairement. Donc, vous devriez d'abord:

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

Vous pouvez alors parcourir et remplacer le texte dans le tableau.

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

cette méthode vous donne un certain contrôle sur les manipulations que vous pouvez effectuer. Ou, vous pouvez simplement faire le remplacement en une seule ligne

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

J'espère que ça aide.


6

Voici comment je l'ai fait avec un gros fichier (50 Go):

J'ai essayé 2 façons différentes: la première, en lisant le fichier en mémoire et en utilisant Regex Replace ou String Replace. Ensuite, j'ai ajouté la chaîne entière à un fichier temporaire.

La première méthode fonctionne bien pour quelques remplacements Regex, mais Regex.Replace ou String.Replace peut provoquer une erreur de mémoire insuffisante si vous effectuez de nombreux remplacements dans un fichier volumineux.

La seconde consiste à lire le fichier temporaire ligne par ligne et à créer manuellement chaque ligne à l'aide de StringBuilder et à ajouter chaque ligne traitée au fichier de résultat. Cette méthode était assez rapide.

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

Ce code a fonctionné pour moi

- //-------------------------------------------------------------------
                           // 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

J'ai tendance à utiliser le code de transfert simple autant que possible, le code ci-dessous a bien fonctionné avec moi

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();
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.