在C#中编辑文本文件的特定行

Lui*_*uis 29 c# stream filestream

我有两个文本文件,Source.txt和Target.txt.源将永远不会被修改并包含N行文本.所以,我想删除Target.txt中的特定文本行,并用Source.txt中的特定文本行替换,我知道我需要的行数,实际上是行号2,两个文件.

我有这样的事情:

string line = string.Empty;
int line_number = 1;
int line_to_edit = 2;

using (StreamReader reader = new StreamReader(@"C:\source.xml"))
{
    using (StreamWriter writer = new StreamWriter(@"C:\target.xml"))
    {
        while ((line = reader.ReadLine()) != null)
        {
            if (line_number == line_to_edit)
            {
                writer.WriteLine(line);
            } 

            line_number++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我打开Writer时,目标文件被擦除,它会写入行,但是,当打开时,目标文件只包含复制的行,其余的则丢失.

我能做什么?

Mar*_*ers 43

如果不重写整个文件,则无法重写行(除非行的长度恰好相同).如果您的文件很小,那么将整个目标文件读入内存然后再将其写出可能是有意义的.你可以这样做:

using System;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        int line_to_edit = 2; // Warning: 1-based indexing!
        string sourceFile = "source.txt";
        string destinationFile = "target.txt";

        // Read the appropriate line from the file.
        string lineToWrite = null;
        using (StreamReader reader = new StreamReader(sourceFile))
        {
            for (int i = 1; i <= line_to_edit; ++i)
                lineToWrite = reader.ReadLine();
        }

        if (lineToWrite == null)
            throw new InvalidDataException("Line does not exist in " + sourceFile);

        // Read the old file.
        string[] lines = File.ReadAllLines(destinationFile);

        // Write the new file over the old file.
        using (StreamWriter writer = new StreamWriter(destinationFile))
        {
            for (int currentLine = 1; currentLine <= lines.Length; ++currentLine)
            {
                if (currentLine == line_to_edit)
                {
                    writer.WriteLine(lineToWrite);
                }
                else
                {
                    writer.WriteLine(lines[currentLine - 1]);
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您的文件很大,最好创建一个新文件,这样您就可以在写入另一个文件时从一个文件中读取流.这意味着您不需要将整个文件同时存储在内存中.你可以这样做:

using System;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        int line_to_edit = 2;
        string sourceFile = "source.txt";
        string destinationFile = "target.txt";
        string tempFile = "target2.txt";

        // Read the appropriate line from the file.
        string lineToWrite = null;
        using (StreamReader reader = new StreamReader(sourceFile))
        {
            for (int i = 1; i <= line_to_edit; ++i)
                lineToWrite = reader.ReadLine();
        }

        if (lineToWrite == null)
            throw new InvalidDataException("Line does not exist in " + sourceFile);

        // Read from the target file and write to a new file.
        int line_number = 1;
        string line = null;
        using (StreamReader reader = new StreamReader(destinationFile))
        using (StreamWriter writer = new StreamWriter(tempFile))
        {
            while ((line = reader.ReadLine()) != null)
            {
                if (line_number == line_to_edit)
                {
                    writer.WriteLine(lineToWrite);
                }
                else
                {
                    writer.WriteLine(line);
                }
                line_number++;
            }
        }

        // TODO: Delete the old file and replace it with the new file here.
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦确定写入操作成功,就可以移动文件(没有抛出异常并且编写器已关闭).

请注意,在这两种情况下,对于行号使用基于1的索引有点令人困惑.在代码中使用基于0的索引可能更有意义.如果您愿意,可以在程序的用户界面中使用基于1的索引,但在进一步发送之前将其转换为0索引.

此外,使用新文件直接覆盖旧文件的缺点是,如果它在中途失败,那么您可能会永久丢失未写入的任何数据.通过先写入第三个文件,您只有在确定有另一个(更正的)副本后才删除原始数据,这样您就可以在计算机中途崩溃时恢复数据.

最后一句:我注意到你的文件有一个xml扩展名.您可能想要考虑使用XML解析器修改文件内容而不是替换特定行更有意义.


小智 41

最简单的方法是:

static void lineChanger(string newText, string fileName, int line_to_edit)
{
     string[] arrLine = File.ReadAllLines(fileName);
     arrLine[line_to_edit - 1] = newText;
     File.WriteAllLines(fileName, arrLine);
}
Run Code Online (Sandbox Code Playgroud)

用法:

lineChanger("new content for this line" , "sample.text" , 34);
Run Code Online (Sandbox Code Playgroud)

  • 这有一个问题,它重写了整个文件。 (5认同)