如何在文件中查找和替换文本

185

目前为止我的代码

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

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


1
请将此注释视为提示:如果您有Visual Studio,可以将文件夹包含在解决方案中,并使用Visual Studio的搜索和替换功能。祝您好运! - StackOrder
7个回答

386

读取文件的全部内容。使用String.Replace进行替换。将内容写回文件。

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

6
“顺便说一下,如果要进行更复杂的替换,可以使用 Regex.Replace。” - Sergey Berezovskiy
46
这会一次性将整个文件读入内存,不总是那么好。 - Banshee
6
我刚刚尝试读取了900万行数据,结果抛出了“内存不足”的异常。 - J.S. Orris
4
对于大文件来说,这是一个更加复杂的问题。需要读取字节块,分析它们,再读取另一个块,依此类推。 - Alexander
9
@Alexander 对的,一段以“...som”结尾,下一段以“e text…”开始。这使问题变得更加复杂。 - djv
显示剩余5条评论

42

即使您不对它们进行更改,也需要将阅读的所有行写入输出文件中。

例如:

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

如果您想在原地执行此操作,则最简单的方法是使用临时输出文件,并在最后使用输出文件替换输入文件。

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

在文本文件中尝试执行更新操作很难保证正确性,因为考虑到大多数编码都是可变长的,使替换后长度相同是很困难的。

编辑:不要使用两个文件操作来替换原始文件,最好使用File.Replace("input.txt", "output.txt", null)。 (请参见MS Docs)。


1
VB 必须更改 2 行代码: 使用 input As New StreamReader(filename) While input.Peek() >= 0 - Brent

41

在读取文件的同时向同一文件写入内容将会很困难。一个快速的解决方法是:

File.WriteAllText("test.txt", File.ReadAllText("test.txt").Replace("some text","some other text"));
你可以使用更好的布局方式:

您可以使用更好的布局方法:

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

5
这很简单,但对于非常大的文件来说并不理想。(注:我不是那个给你负评的人) - Alvin Wong
3
我同意,但在读取文件时无法向其写入内容。除非将内容写入不同的文件,然后进行重命名替换...无论哪种方式,构建新文件时都必须将其存储在其他位置,无论是在内存中还是在磁盘上,都需要占用存储空间。 - Flynn1179
@Flynn1179 在这个例子中不是真的。它是有效的。试一下。我猜 ReadAllTextWriteAllText 之前关闭了文件访问权限。我在自己的应用程序中也使用了这种技术。 - SteveCinq
我知道,这个例子在读取时不会写入,这就是我的观点! - Flynn1179
这是一个相当不错的例子,我的意思是很多人不需要用它来处理大文件..我们中的一些人对于像这样的简单方法和一个只有2000行的小文件感到满意。 - user3548161

11
这是我处理一个大文件(50GB)的方法:
我尝试过两种不同的方法:第一种是将文件读入内存,然后使用正则表达式或字符串替换。然后我将整个字符串追加到临时文件中。
第一种方法适用于少量正则表达式替换,但是如果您对大文件进行多次替换,则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();
    }

10

很可能你需要将文本文件加载到内存中,然后进行替换。然后你需要使用你清楚知道的方法来覆盖文件。所以你首先需要:

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

您可以遍历数组并替换其中的文本。

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

这种方法使您能够对可以进行的操作拥有一定的控制。或者,您可以仅在一行中进行替换。

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

希望这能帮到您。

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

-1
这段代码对我有效。
- //-------------------------------------------------------------------
                           // 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);
                           }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接