Como localizar e substituir texto em um arquivo com c #

157

Meu código até agora

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

Eu sei como encontrar o texto, mas não tenho idéia de como substituir o texto no arquivo pelo meu.

Win Coder
fonte
Considere este comentário como apenas uma dica: Se você tiver o Visual Studio, você pode incluir as pastas na solução e usar a busca e característica do visual studio .best de sorte substituir
StackOrder
Possível duplicado de Abra um arquivo e substituir cordas em C #
RecklessSergio

Respostas:

321

Leia todo o conteúdo do arquivo. Faça uma substituição com String.Replace. Grave o conteúdo novamente no arquivo.

string text = File.ReadAllText("test.txt");
text = text.Replace("some text", "new value");
File.WriteAllText("test.txt", text);
Sergey Berezovskiy
fonte
5
@WinCoder BTW para substituições mais complexas você pode usarRegex.Replace
Sergey Berezovskiy
35
Isso lê o arquivo inteiro na memória de uma vez, nem sempre tão bom.
Banshee
6
@Banshee Touche 'Acabei de tentar ler 9.000.000 de linhas e foi lançada uma System out of memoryexceção.
Squ1rr3lz
4
Para arquivos grandes, é uma questão mais complexa. Leia pedaço de byte, analise-o, leia outro pedaço, etc. #
Alexander Alexander
6
@Alexander Right. Um pedaço termina com "... som" e o próximo começa com "e texto ...". Torna um problema muito mais complicado.
djv 16/05
36

É difícil escrever no mesmo arquivo que você está lendo. Uma maneira rápida é simplesmente fazer isso:

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

Você pode definir melhor isso com

string str = File.ReadAllText("test.txt");
str = str.Replace("some text","some other text");
File.WriteAllText("test.txt", str);
Flynn1179
fonte
3
Isso é simples, mas não é desejável para arquivos muito grandes. (ps eu não sou o único que downvoted)
Alvin Wong
3
Eu concordo, mas você não pode gravar no arquivo enquanto estiver lendo. A menos que você escreva para um arquivo diferente, substitua-o por um renomear depois .. de qualquer maneira, o novo arquivo deverá ser armazenado em outro lugar enquanto você o estiver construindo, seja na memória ou no disco.
Flynn1179
@ Flynn1179 Não é verdade neste exemplo. Funciona. Experimente. Eu acho que o ReadAllTextfecha o acesso a arquivos antes WriteAllText. Eu uso essa mesma técnica em meu próprio aplicativo.
19318 SteveCinq
Eu sei; este exemplo não escreve enquanto está lendo, esse foi o meu ponto!
Flynn1179
27

Você precisa escrever todas as linhas que lê no arquivo de saída, mesmo que não as altere.

Algo como:

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

Se você deseja executar esta operação no local, a maneira mais fácil é usar um arquivo de saída temporário e, no final, substituir o arquivo de entrada pela saída.

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

(É difícil acertar a execução de operações de atualização no meio do arquivo de texto, pois sempre é difícil ter a substituição do mesmo tamanho, pois a maioria das codificações tem largura variável.)

Edição: em vez de duas operações de arquivo para substituir o arquivo original, melhor usar File.Replace("input.txt", "output.txt", null). (Consulte MSDN .)

Richard
fonte
1
O VB teve que alterar 2 linhas: Usando input como novo StreamReader (nome do arquivo) Enquanto input.Peek ()> = 0
Brent
8

É provável que você precise puxar o arquivo de texto para a memória e fazer as substituições. Você precisará substituir o arquivo usando o método que você conhece claramente. Então você primeiro:

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

Você pode percorrer e substituir o texto na matriz.

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

esse método fornece controle sobre as manipulações que você pode fazer. Ou, você pode simplesmente fazer a substituição em uma linha

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

Eu espero que isso ajude.

Cavaleiro da Lua
fonte
6

Foi assim que fiz com um arquivo grande (50 GB):

Tentei duas maneiras diferentes: a primeira, lendo o arquivo na memória e usando Regex Replace ou String Replace. Em seguida, anexei a string inteira a um arquivo temporário.

O primeiro método funciona bem para algumas substituições de Regex, mas Regex.Replace ou String.Replace pode causar erro de falta de memória se você fizer muitas substituições em um arquivo grande.

A segunda é lendo o arquivo temporário linha por linha e construindo manualmente cada linha usando StringBuilder e anexando cada linha processada ao arquivo de resultado. Este método foi bem rápido.

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();
    }
amor ao vivo
fonte
0

Este código funcionou para mim

- //-------------------------------------------------------------------
                           // 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);
                           }
poder da radão
fonte
0

eu tendem a usar o código simples de encaminhamento o máximo que posso, o código abaixo funcionou bem comigo

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