简体   繁体   English

在C#中替换文本文件中特定行的最佳方法

[英]Best approach to replace specific lines in a text file in c#

For the following operation: 对于以下操作:

  1. Open a text file 打开一个文本文件
  2. Search and replace all searching characters with new characters 搜索并用新字符替换所有搜索字符

I'd like to achieve above in c#, here is my code: 我想在C#中实现以上功能,这是我的代码:

using (StreamReader sr = new StreamReader(@"S:\Personal Folders\A\TESTA.txt"))
{
    using (StreamWriter sw = new StreamWriter(@"S:\Personal Folders\A\TESTB.txt"))
    {
        string line;

        while ((line = sr.ReadLine())!= null)
        {               
            if (!line.Contains("before"))
            {
                sw.WriteLine(line);
            }

            else if (line.Contains("before"))
            {
                sw.WriteLine(line.Replace("before", "after"));
            }
        }
    }
}

Basically, the above code will generate a new file with the desired replace operation, but as you can see, the way I am doing is read each line of the original file and write to a new file. 基本上,以上代码将使用所需的替换操作生成一个新文件,但是如您所见,我的工作方式是读取原始文件的每一行并写入一个新文件。 This could achieve my goal, but it may have system IO issue because it is reading and writing for each line. 这可以实现我的目标,但可能会出现系统IO问题,因为它正在读取和写入每一行。 Also, I cannot read all the lines to an array first, and then write, because the file is large and if I try to write to an string[] , replace all, then write the array to the file, will bring about the memory timeout issue. 另外,由于文件很大,因此我无法先读取所有行然后写入数组,因为文件很大,如果我尝试写入string[] ,则替换所有内容,然后将数组写入文件,将带来内存超时问题。

Is there any way that I can just locate to the specific lines, and just replace those lines and keep all the rest? 有什么方法可以定位到特定的行,然后替换那些行并保留其余所有行? Or What is the best way to solve the above problem? 或解决上述问题的最佳方法是什么? Thanks 谢谢

In general, what you are doing is correct, possibly followed by some renames to replace the original file. 通常,您所做的是正确的,可能随后进行了一些重命名以替换原始文件。 If you do want to replace the original file, you should rename the original file to a temporary name, rename the new file to the original name, and then either leave or delete the original file. 如果确实要替换原始文件,则应将原始文件重命名为临时名称,将新文件重命名为原始名称,然后保留或删除原始文件。 You must handle conflicts with your temporary name and errors in all renames. 您必须处理与您的临时名称的冲突以及所有重命名中的错误。

Consider you are replacing a six character string with a five character string - if you write back to the original file, what will you do with the extra characters? 考虑要用五个字符串替换六个字符串-如果您写回原始文件,多余的字符将如何处理? Files are stored on disk as raw bytes of data, there is no "text" file on disk. 文件作为数据的原始字节存储在磁盘上,磁盘上没有“文本”文件。 What if you replace a string with a longer one - you then potentially have to move the entire rest of the file to make room to write the longer line. 如果用较长的字符串替换字符串,该怎么办-然后可能必须移动文件的其余部分以腾出空间来写入较长的行。

You can imagine the file on disk as letters written on graph paper in the boxes. 您可以将磁盘上的文件想象成写在方格纸上的字母。 The end of each line is noted by a special character (or characters - in Windows, that is CRLF), the characters fill all the boxes horizontally. 每行的末尾都有一个特殊字符(或Windows中的字符,即CRLF),这些字符会水平填充所有框。 If you tried to replace words on the graph paper you would have to erase and re-write lots of letters. 如果您试图替换方格纸上的单词,则必须擦除并重写大量字母。 Writing on a new sheet will be easiest. 在新纸上书写将是最简单的。

Well, your approach is basically fine... but I wouldn't check if the line contains the word before ... the trade-off is not good enough: 好吧,您的方法基本上很好...但是我不会检查该行before是否包含单词...权衡不够好:

using (StreamReader sr = new StreamReader(@"S:\Personal Folders\A\TESTA.txt"))
{
    using (StreamWriter sw = new StreamWriter(@"S:\Personal Folders\A\TESTB.txt"))
    {
        String line;

        while ((line = sr.ReadLine()) != null)
            sw.WriteLine(line.Replace("before", "after"));
    }
}

I don't know what IO issue you are worried about, but your code should work ok. 我不知道您担心什么IO问题,但是您的代码应该可以正常工作。 You can code more concisely as follows: 您可以更简洁地编写如下代码:

using (StreamReader sr = new StreamReader(@"S:\Personal Folders\A\TESTA.txt"))
{
    using (StreamWriter sw = new StreamWriter(@"S:\Personal Folders\A\TESTB.txt"))
    {
        while ((string line = sr.ReadLine())!= null)
        {
            sw.WriteLine(line.Replace("before", "after"));
        }
    }
}

This will run a bit faster because it searches for "before" only once per line. 这将运行得更快一些,因为它每行只搜索一次“ before”。 By default the StreamWriter buffers your writes and does not flush to the disk each time you call WriteLine, and file IO is asynchronous in the operating system, so don't worry so much about IO. 默认情况下,StreamWriter会缓冲您的写入操作,并且每次调用WriteLine时都不会刷新到磁盘,并且文件IO在操作系统中是异步的,因此不必担心IO。

Try following : 尝试以下操作:

else if (line.Contains("before"))
{
    sw.WriteLine(line.Replace("before", "after"));
    sw.Write(sr.ReadToEnd());
    break;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM