如何使用C#查找和替换文件中的文本

Win*_*der 147 .net c# io file-handling streamreader

我的代码到目前为止

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

我知道如何找到文本,但我不知道如何用我自己的文件替换文件中的文本.

Ser*_*kiy 295

阅读所有文件内容.替换为String.Replace.将内容写回文件.

string text = File.ReadAllText("test.txt");
text = text.Replace("some text", "new value");
File.WriteAllText("test.txt", text);
Run Code Online (Sandbox Code Playgroud)

  • 这会立即将整个文件读取到内存中,并不总是那么好. (29认同)
  • @Banshee Touche'我刚刚尝试读取9,000,000行,并抛出了`System out of memory`异常. (6认同)
  • @Alexander对.一个块以"...... som"结尾,下一个以"e text ..."开头.使它成为一个更复杂的问题. (6认同)
  • @WinCoder*BTW*对于更复杂的替换,您可以使用`Regex.Replace` (5认同)
  • 对于大文件,这是一个更复杂的问题.读取字节块,分析它们,读取另一个块等. (4认同)
  • @djv 对于分块方法,我认为如果在每个块之后将文件指针移回搜索文本的长度,它可能会起作用。将块写入新的临时文件时,您必须进行相同的调整,但我认为这将涵盖搜索文本有时位于块之间的问题 (2认同)

Fly*_*179 35

您将很难写入您正在阅读的同一文件.一个简单的方法是简单地这样做:

File.WriteAllText("test.txt", File.ReadAllText("test.txt").Replace("some text","some other text"));
Run Code Online (Sandbox Code Playgroud)

你可以更好地解决这个问题

string str = File.ReadAllText("test.txt");
str = str.Replace("some text","some other text");
File.WriteAllText("test.txt", str);
Run Code Online (Sandbox Code Playgroud)

  • 这很简单,但对于非常大的文件不可取.(ps我不是那个投票的人) (3认同)
  • 我同意,但是当你从中读取文件时,你不能写入文件.除非你写出一个不同的文件,然后用一个重命名替换它.无论如何,新文件必须存储在你构建它的其他地方,无论是在内存还是在磁盘上. (3认同)

Ric*_*ard 27

您需要将读取的所有行写入输出文件,即使您不更改它们也是如此.

就像是:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

如果要在适当的位置执行此操作,则最简单的方法是使用临时输出文件,最后用输出替换输入文件.

File.Delete("input.txt");
File.Move("output.txt", "input.txt");
Run Code Online (Sandbox Code Playgroud)

(尝试在文本文件中间执行更新操作很难做到正确,因为如果大多数编码都是可变宽度的话,总是让替换长度相同是很难的.)

编辑:而不是两个文件操作来替换原始文件,更好地使用File.Replace("input.txt", "output.txt", null).(参见MSDN.)


Moo*_*ght 8

您可能需要将文本文件拉入内存然后进行替换.然后,您必须使用您清楚了解的方法覆盖该文件.所以你会先:

// Read lines from source file.
string[] arr = File.ReadAllLines(file);
Run Code Online (Sandbox Code Playgroud)

然后你可以循环并替换数组中的文本.

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);
}
Run Code Online (Sandbox Code Playgroud)

这种方法可以控制你可以做的操作.或者,您只能在一行中进行替换

File.WriteAllText("test.txt", text.Replace("match", "new value"));
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.


Ali*_*Ali 8

我倾向于尽可能多地使用简单的前向代码,下面的代码对我来说效果很好

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();
}
Run Code Online (Sandbox Code Playgroud)


liv*_*ove 7

这就是我使用大型(50 GB)文件的方式:

我尝试了两种不同的方法:第一种,将文件读入内存并使用 Regex Replace 或 String Replace。然后我将整个字符串附加到一个临时文件中。

第一种方法适用于一些 Regex 替换,但如果您在一个大文件中进行多次替换,Regex.Replace 或 String.Replace 可能会导致内存不足错误。

第二种是通过逐行读取临时文件并使用 StringBuilder 手动构建每一行并将每个处理过的行附加到结果文件中。这个方法相当快。

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();
    }
Run Code Online (Sandbox Code Playgroud)