Nasıl bir dosyadaki metni C # ile bulma ve değiştirme


157

Kodum şu ana kadar

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

Metni nasıl bulacağımı biliyorum, ancak dosyadaki metnin kendimle nasıl değiştirileceği hakkında hiçbir fikrim yok.


Bu yorumu yalnızca bir ipucu olarak düşünün: Görsel stüdyo varsa, çözümü klasöre dahil edebilir ve görsel stüdyoda arama ve değiştirme özelliğini kullanabilirsiniz. Şansın
iyisi

Yanıtlar:


322

Tüm dosya içeriğini okuyun. İle bir yedek yapın String.Replace. İçeriği dosyaya geri yazın.

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

5
Kullanabileceğiniz daha karmaşık değiştirme işlemleri için @WinCoder BTWRegex.Replace
Sergey Berezovskiy

35
Bu, tüm dosyayı bir kerede belleğe okur, her zaman iyi değildir.
Banshee

6
@Banshee Touche 'Sadece 9.000.000 satırı okumaya çalıştım ve bir System out of memoryistisna atıldım .
Squ1rr3lz

4
Büyük dosyalar için daha karmaşık bir konudur. Bayt yığınını okuyun, analiz edin, başka bir yığın okuyun, vb.
Alexander

6
@Alexander Doğru. Bir parça "... som" ile biter, diğeri "e metin ..." ile başlar. Çok daha karmaşık bir problem haline getirir.
djv

36

Okuduğunuz dosyaya yazmakta zorlanacaksınız. Bunun hızlı bir yolu bunu yapmaktır:

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

Bunu daha iyi düzenleyebilirsiniz

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

3
Bu basittir ancak çok büyük dosyalar için istenmez. (ps Ben düşürülen kişi değilim)
Alvin Wong

3
Kabul ediyorum, ancak dosyadan okurken dosyaya yazamazsınız. Farklı bir dosyaya yazmadıkça, daha sonra yeniden adlandır ile değiştirin. Her iki durumda da, yeni dosya, ister bellekte ister diskte olsun, onu oluştururken başka bir yerde saklanmalıdır.
Flynn1179

@ Flynn1179 Bu örnekte doğru değil. İşe yarıyor. Denemek. ReadAllTextÖnce dosya erişimi kapanır sanırım WriteAllText. Bu uygulamayı kendi uygulamamda kullanıyorum.
SteveCinq

Biliyorum; bu örnek okurken yazmıyor, benim amacım buydu!
Flynn1179

27

Okumadığınız tüm satırları değiştirmeseniz bile çıktı dosyasına yazmanız gerekir.

Gibi bir şey:

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

Bu işlemi yerinde yapmak istiyorsanız, en kolay yol geçici bir çıktı dosyası kullanmak ve sonunda girdi dosyasını çıktı ile değiştirmek.

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

(Metin dosyasının ortasındaki güncelleme işlemlerini gerçekleştirmeye çalışmak oldukça zordur, çünkü çoğu kodlama değişken genişlik olduğu için her zaman aynı uzunlukta olması zordur.)

EDIT: yerine orijinal dosya yerine iki dosya işlemleri, kullanımı daha iyi File.Replace("input.txt", "output.txt", null). (Bkz. MSDN .)


1
VB 2 satır değiştirmek zorunda kaldı: Girdi Yeni StreamReader olarak kullanma (dosya adı) input.Peek ()> = 0
Brent

8

Büyük olasılıkla metin dosyasını belleğe çekmeniz ve değiştirmeleri yapmanız gerekecektir. Daha sonra, açıkça bildiğiniz yöntemi kullanarak dosyanın üzerine yazmanız gerekecektir. İlk önce:

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

Daha sonra dizideki metni döngüye alabilir ve değiştirebilirsiniz.

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

bu yöntem, yapabileceğiniz manipülasyonlar üzerinde size biraz kontrol sağlar. Veya sadece bir satırda değiştirme yapabilirsiniz

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

Umarım bu yardımcı olur.


6

Büyük (50 GB) bir dosya ile böyle yaptım:

Ben 2 farklı şekilde denedim: birincisi, dosyayı belleğe okuma ve Regex Replace veya String Replace kullanarak. Sonra tüm dizeyi geçici bir dosyaya ekledim.

İlk yöntem birkaç Regex değişikliği için iyi çalışır, ancak büyük bir dosyada çok sayıda değişiklik yaparsanız Regex.Replace veya String.Replace bellek yetersizliğine neden olabilir.

İkincisi geçici dosyayı satır satır okuyarak ve her satırı StringBuilder kullanarak manuel olarak oluşturarak ve işlenen her satırı sonuç dosyasına ekleyerek. Bu yöntem oldukça hızlıydı.

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

Bu kod benim için çalıştı

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

i olabildiğince basit ileri kod kullanma eğilimindedir, aşağıdaki kod benimle iyi çalıştı

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();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.