วิธีการค้นหาและแทนที่ข้อความในไฟล์ด้วย C #


157

รหัสของฉันจนถึงตอนนี้

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

ฉันรู้วิธีค้นหาข้อความ แต่ฉันไม่มีความคิดเกี่ยวกับวิธีการแทนที่ข้อความในไฟล์ด้วยตัวฉันเอง


พิจารณาความคิดเห็นนี้เป็นคำแนะนำเท่านั้น: หากคุณมี visual studio คุณสามารถรวมโฟลเดอร์ในโซลูชันและใช้การค้นหาและแทนที่ฟีเจอร์ของ visual studio โชคดีที่สุด
StackOrder

มีความเป็นไปได้ที่ซ้ำกันของการเปิดไฟล์และแทนที่สตริงใน C #
RecklessSergio

คำตอบ:


321

อ่านเนื้อหาไฟล์ทั้งหมด String.Replaceให้ทดแทนด้วย เขียนเนื้อหากลับไปเป็นไฟล์

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

5
@WinCoder BTWการเปลี่ยนที่ซับซ้อนมากขึ้นคุณสามารถใช้Regex.Replace
Sergey Berezovskiy

35
นี้จะอ่านไฟล์ทั้งหมดไปยังหน่วยความจำในครั้งเดียวไม่ดีเสมอไป
Banshee

6
@Beehee Touche 'ฉันแค่พยายามอ่าน 9,000,000 แถวและได้รับการSystem out of memoryยกเว้น
Squ1rr3lz

4
สำหรับไฟล์ขนาดใหญ่มันเป็นปัญหาที่ซับซ้อนกว่า อ่านอันไบต์วิเคราะห์พวกเขาอ่านอันอื่นเป็นต้น
Alexander

6
@Alexander ขวา ก้อนอันหนึ่งลงท้ายด้วย "... ส้ม" และอีกอันเริ่มต้นด้วย "e text ... " ทำให้เป็นปัญหาที่ซับซ้อนมากขึ้น
djv

36

คุณกำลังจะมีเวลาเขียนยากไปยังไฟล์เดียวกันที่คุณกำลังอ่านจาก วิธีหนึ่งที่รวดเร็วก็คือทำสิ่งนี้:

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

3
มันง่าย แต่ไม่เป็นที่ต้องการสำหรับไฟล์ที่มีขนาดใหญ่มาก (ps ฉันไม่ใช่คนที่ลงคะแนน)
อัลวินหว่อง

3
ฉันเห็นด้วย แต่คุณไม่สามารถเขียนไฟล์ในขณะที่คุณกำลังอ่านได้ หากคุณไม่เขียนลงในไฟล์อื่นให้เปลี่ยนเป็นชื่อใหม่หลังจากนั้น .. ไม่ว่าจะด้วยวิธีใดไฟล์ใหม่จะต้องถูกเก็บไว้ที่อื่นในขณะที่คุณกำลังสร้างไฟล์ไม่ว่าจะเป็นหน่วยความจำหรือดิสก์
Flynn1179

@ Flynn1179 ไม่เป็นความจริงในตัวอย่างนี้ มันได้ผล. ลองดู ฉันเดาปิดปิดการเข้าถึงแฟ้มก่อนที่จะReadAllText WriteAllTextฉันใช้เทคนิคนี้ในแอพของฉันเอง
SteveCinq

ฉันรู้ว่า; ตัวอย่างนี้ไม่ได้เขียนในขณะที่อ่านนั่นคือประเด็นของฉัน!
Flynn1179

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

หากคุณต้องการดำเนินการนี้แทนวิธีที่ง่ายที่สุดคือการใช้ไฟล์เอาต์พุตชั่วคราวและในตอนท้ายให้แทนที่ไฟล์อินพุตด้วยเอาต์พุต

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

(การพยายามดำเนินการอัปเดตที่อยู่ตรงกลางของไฟล์ข้อความนั้นค่อนข้างยากที่จะทำให้ถูกต้องเพราะการเปลี่ยนความยาวเท่ากันนั้นจะยากลำบากเพราะการเข้ารหัสส่วนใหญ่เป็นความกว้างของตัวแปร)

แก้ไข:File.Replace("input.txt", "output.txt", null)มากกว่าสองแฟ้มการดำเนินงานที่จะเปลี่ยนไฟล์ต้นฉบับดีกว่าที่จะใช้ (ดูMSDN )


1
VB ต้องเปลี่ยน 2 บรรทัด: การใช้อินพุตเป็น New StreamReader (ชื่อไฟล์) ในขณะที่ input.Peek ()> = 0
Brent

8

มีโอกาสที่คุณจะต้องดึงไฟล์ข้อความลงในหน่วยความจำแล้วทำการเปลี่ยนใหม่ จากนั้นคุณจะต้องเขียนทับไฟล์โดยใช้วิธีที่คุณทราบอย่างชัดเจน ดังนั้นคุณจะก่อน:

// 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"));

ฉันหวังว่านี่จะช่วยได้.


6

นี่คือวิธีที่ฉันทำกับไฟล์ขนาดใหญ่ (50 GB):

ฉันลองวิธีที่ต่างกัน 2 วิธี: วิธีแรกคืออ่านไฟล์ในหน่วยความจำและใช้ Regex Replace หรือ String Replace จากนั้นฉันต่อท้ายสตริงทั้งหมดลงในไฟล์ชั่วคราว

วิธีแรกทำงานได้ดีสำหรับการเปลี่ยน Regex สองสามครั้ง แต่ Regex.Replace หรือ String.Replace อาจทำให้เกิดข้อผิดพลาดของหน่วยความจำไม่ได้หากคุณทำการแทนที่หลายครั้งในไฟล์ขนาดใหญ่

ข้อที่สองคือการอ่านไฟล์ temp ทีละบรรทัดและสร้างแต่ละบรรทัดด้วยตนเองโดยใช้ 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();
    }

0

รหัสนี้ใช้ได้สำหรับฉัน

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

ฉันมักจะใช้รหัสไปข้างหน้าอย่างง่ายเท่าที่จะทำได้รหัสด้านล่างทำงานได้ดีกับฉัน

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();
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.