Cách tìm và thay thế văn bản trong tệp bằng C #


157

Mã của tôi cho đến nay

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

Tôi biết cách tìm văn bản, nhưng tôi không biết làm thế nào để thay thế văn bản trong tệp bằng chính tôi.


Chỉ xem xét nhận xét này như một mẹo: Nếu bạn có phòng thu trực quan, bạn có thể bao gồm các thư mục trong giải pháp và sử dụng tính năng tìm kiếm và thay thế của phòng thu trực quan. Chúc may mắn
StackOrder

Câu trả lời:


321

Đọc tất cả nội dung tập tin. Hãy thay thế bằng String.Replace. Viết nội dung trở lại tập tin.

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

5
@WinCoder BTW cho các thay thế phức tạp hơn mà bạn có thể sử dụngRegex.Replace
Sergey Berezovskiy

35
Điều này đọc toàn bộ tập tin vào bộ nhớ cùng một lúc, không phải lúc nào cũng tốt.
Banshee

6
@Banshee Touche 'Tôi vừa thử đọc 9.000.000 hàng và bị ném System out of memoryngoại lệ.
Squ1rr3lz

4
Đối với các tệp lớn, đó là vấn đề phức tạp hơn. Đọc đoạn mã byte, phân tích chúng, đọc đoạn khác, v.v.
Alexander

6
@Alexander Phải. Một đoạn kết thúc bằng "... som" và phần tiếp theo bắt đầu bằng "văn bản điện tử ...". Làm cho nó một vấn đề phức tạp hơn nhiều.
djv

36

Bạn sẽ gặp khó khăn khi viết vào cùng một tệp mà bạn đang đọc. Một cách nhanh chóng là chỉ cần làm điều này:

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

Bạn có thể đặt nó ra tốt hơn với

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

3
Điều này là đơn giản nhưng không mong muốn cho tập tin rất lớn. (ps Tôi không phải là người bị đánh giá thấp)
Alvin Wong

3
Tôi đồng ý, nhưng bạn không thể ghi vào tệp trong khi bạn đọc từ đó. Trừ khi bạn ghi ra một tệp khác, sau đó thay thế nó bằng một tên đổi tên .. bằng cách nào đó, tệp mới phải được lưu trữ ở một nơi khác trong khi bạn đang xây dựng nó, cho dù đó là trong bộ nhớ hoặc trên đĩa.
Flynn1179

@ Flynn1179 Không đúng trong ví dụ này. Nó hoạt động. Hãy thử nó. Tôi đoán việc ReadAllTextđóng quyền truy cập tập tin trước WriteAllText. Tôi sử dụng chính kỹ thuật này trong ứng dụng của riêng tôi.
SteveCinq

Tôi biết; ví dụ này không viết trong khi đọc, đó là quan điểm của tôi!
Flynn1179

27

Bạn cần viết tất cả các dòng bạn đọc vào tệp đầu ra, ngay cả khi bạn không thay đổi chúng.

Cái gì đó như:

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

Nếu bạn muốn thực hiện thao tác này tại chỗ thì cách dễ nhất là sử dụng tệp đầu ra tạm thời và cuối cùng thay thế tệp đầu vào bằng đầu ra.

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

(Cố gắng thực hiện các hoạt động cập nhật ở giữa tệp văn bản là khá khó để thực hiện đúng vì luôn luôn có sự thay thế có cùng độ dài là khó vì hầu hết các mã hóa đều có chiều rộng thay đổi.)

EDIT: Thay vì hai thao tác tệp để thay thế tệp gốc, tốt hơn nên sử dụng File.Replace("input.txt", "output.txt", null). (Xem MSDN .)


1
VB đã phải thay đổi 2 dòng: Sử dụng đầu vào là StreamReader mới (tên tệp) Trong khi input.Peek ()> = 0
Brent

8

Có khả năng bạn sẽ phải kéo tệp văn bản vào bộ nhớ và sau đó thực hiện thay thế. Sau đó, bạn sẽ phải ghi đè lên tệp bằng phương pháp bạn biết rõ. Vì vậy, bạn sẽ đầu tiên:

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

YOu sau đó có thể lặp qua và thay thế văn bản trong mảng.

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

phương pháp này cung cấp cho bạn một số kiểm soát đối với các thao tác bạn có thể làm. Hoặc, bạn chỉ có thể thực hiện thay thế trong một dòng

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

Tôi hi vọng cái này giúp được.


6

Đây là cách tôi đã làm với một tệp lớn (50 GB):

Tôi đã thử 2 cách khác nhau: cách thứ nhất, đọc tệp vào bộ nhớ và sử dụng Regex Thay thế hoặc Thay thế chuỗi. Sau đó, tôi nối toàn bộ chuỗi vào một tệp tạm thời.

Phương thức đầu tiên hoạt động tốt đối với một vài thay thế Regex, nhưng Regex.Replace hoặc String.Replace có thể gây ra lỗi bộ nhớ nếu bạn thực hiện nhiều thay thế trong một tệp lớn.

Thứ hai là bằng cách đọc dòng tệp tạm thời theo từng dòng và xây dựng thủ công từng dòng bằng StringBuilder và nối thêm từng dòng được xử lý vào tệp kết quả. Phương pháp này khá nhanh.

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

Mã này đã làm việc cho tôi

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

tôi có xu hướng sử dụng mã chuyển tiếp đơn giản hết mức có thể, mã bên dưới hoạt động tốt với tôi

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();
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.