185

My code so far

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

I know how to find the text, but I have no idea on how to replace the text in the file with my own.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Win Coder
  • 6,628
  • 11
  • 54
  • 81
  • 1
    Consider this comment as a tip only : If you have visual studio ,you can include the folders in the solution and use the search and replace feature of visual studio .Best of luck – StackOrder Jan 16 '18 at 11:22
  • Possible duplicate of [Open a file and replace strings in C#](https://stackoverflow.com/questions/1915632/open-a-file-and-replace-strings-in-c-sharp) – RecklessSergio Jul 29 '19 at 09:44

7 Answers7

384

Read all file content. Make a replacement with String.Replace. Write content back to file.

string text = File.ReadAllText("test.txt");
text = text.Replace("some text", "new value");
File.WriteAllText("test.txt", text);
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • 6
    @WinCoder *BTW* for more complex replacements you can use `Regex.Replace` – Sergey Berezovskiy Nov 22 '12 at 09:50
  • 46
    This reads the entire file to memory at once, not always that good. – Banshee Jun 04 '15 at 09:32
  • 6
    @Banshee Touche' I just tried to read 9,000,000 rows and was thrown a `System out of memory` exception. – J.S. Orris Aug 06 '15 at 00:22
  • 4
    For large files it's more complex issue. Read byte chunk, analyze them, read another chunk, etc. – Alexander Sep 09 '15 at 14:36
  • 9
    @Alexander Right. One chunk ends with "...som", and the next begins with "e text...". Makes it a much more complicated problem. – djv May 16 '16 at 20:11
  • Very helpful and simple solution! – rollingthedice Sep 23 '17 at 11:42
  • 2
    @djv For the chunking method, I think it might work if you move the file pointer back the length of the search text after each chunk. You'll have to make the same adjustment when writing the chunk to the new temp file, but i think that would cover the problem of the search text sometimes being in between chunks – user1760150 Nov 02 '18 at 13:47
  • How to realize it in VB? Thanks – user618520 Jan 17 '20 at 08:42
  • This also has another issue eg: when editing a line that has "1.2" to "1.234", it also affects another line if it contains"1.23" –  Mar 17 '21 at 16:41
  • The `ReadAllText` and `WriteAllText` methods have overloads that takes an encoding. I usually end up passing `Encoding.UTF8` to avoid Unicode problems. – dana Sep 05 '22 at 21:34
42

You need to write all the lines you read into the output file, even if you don't change them.

Something like:

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

If you want to perform this operation in place then the easiest way is to use a temporary output file and at the end replace the input file with the output.

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

(Trying to perform update operations in the middle of text file is rather hard to get right because always having the replacement the same length is hard given most encodings are variable width.)

EDIT: Rather than two file operations to replace the original file, better to use File.Replace("input.txt", "output.txt", null). (See MS Docs.)

Richard
  • 106,783
  • 21
  • 203
  • 265
  • 1
    VB had to change 2 lines: Using input As New StreamReader(filename) While input.Peek() >= 0 – Brent Feb 06 '15 at 16:04
41

You're going to have a hard time writing to the same file you're reading from. One quick way is to simply do this:

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

You can lay that out better with

string str = File.ReadAllText("test.txt");
str = str.Replace("some text","some other text");
File.WriteAllText("test.txt", str);
Flynn1179
  • 11,925
  • 6
  • 38
  • 74
  • 5
    This is simple but not desirable for very-large file. (p.s. I am not the one who downvoted) – Alvin Wong Nov 22 '12 at 09:38
  • 3
    I'd agree, but you can't write to the file while you're reading from it. Unless you write out to a different file, then replace it with a rename afterwards.. either way, the new file has to be stored somewhere else while you're building it, whether it's in memory or on disk. – Flynn1179 Nov 22 '12 at 09:41
  • @Flynn1179 Not true in this example. It works. Try it out. I guess the `ReadAllText` closes off file access prior to `WriteAllText`. I use this very technique in my own app. – SteveCinq May 19 '18 at 17:10
  • I know; this example doesn't write while it's reading, that was my point! – Flynn1179 May 21 '18 at 08:12
  • It's a pretty good example i mean alot of people dont need to use this for large file processing .. some of us are happy with a tiny 2000 line file with a straight forward method like this. – user3548161 Jan 14 '21 at 04:53
11

This is how I did it with a large (50 GB) file:

I tried 2 different ways: the first, reading the file into memory and using Regex Replace or String Replace. Then I appended the entire string to a temporary file.

The first method works well for a few Regex replacements, but Regex.Replace or String.Replace could cause out of memory error if you do many replaces in a large file.

The second is by reading the temp file line by line and manually building each line using StringBuilder and appending each processed line to the result file. This method was pretty fast.

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-love
  • 48,840
  • 22
  • 240
  • 204
10

It is likely you will have to pull the text file into memory and then do the replacements. You will then have to overwrite the file using the method you clearly know about. So you would first:

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

YOu can then loop through and replace the text in the 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);
}

this method gives you some control on the manipulations you can do. Or, you can merely do the replace in one line

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

I hope this helps.

MoonKnight
  • 23,214
  • 40
  • 145
  • 277
8

i tend to use simple forward code as much as i can ,below code worked fine with 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();
}
Ali
  • 1,080
  • 16
  • 22
-1

This code Worked for 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);
                           }
ranojan
  • 819
  • 8
  • 11