Як знайти та замінити текст у файлі на 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");
      }
}

Я знаю, як знайти текст, але я не маю уявлення про те, як замінити текст у файлі своїм.


Розгляньте цей коментар лише як підказку: Якщо у вас є візуальна студія, ви можете включити папки в рішення і використовувати функцію пошуку та заміни візуальної студії.
Найкраща

Відповіді:


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
Сергій Березовський

35
Це зчитує весь файл в пам'ять одразу, не завжди це добре.
Banshee

6
@Banshee Touche 'Я щойно спробував прочитати 9000000 рядків, і мене виняли System out of memoryвинятком.
Squ1rr3lz

4
Для великих файлів це складніше питання. Прочитайте шматок байтів, проаналізуйте їх, прочитайте ще один фрагмент тощо
Олександр

6
@ Олександр Право. Один шматок закінчується на "... сом", а наступний починається з "е тексту ...". Це робить набагато складнішою проблему.
dvv

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 рядки: Використання введення в якості нового 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 Гб):

Я спробував 2 різних способи: перший, зчитування файлу в пам'яті та використання 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();
    }

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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.