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

时间:2023-02-03
本文介绍了在 C# 中编辑文本文件的特定行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

我有这样的东西:

string line = string.Empty;int line_number = 1;int line_to_edit = 2;使用 StreamReader reader = new StreamReader(@C:	arget.xml");使用 StreamWriter writer = new StreamWriter(@C:	arget.xml");while ((line = reader.ReadLine()) != null){if (line_number == line_to_edit)writer.WriteLine(line);line_number++;}

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

我能做什么?

解决方案

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

使用系统;使用 System.IO;课程计划{静态无效主(字符串 [] args){int line_to_edit = 2;//警告:基于 1 的索引!string sourceFile = "source.txt";string destinationFile = "target.txt";//从文件中读取适当的行.字符串 lineToWrite = null;使用 (StreamReader reader = new StreamReader(sourceFile)){for (int i = 1; i <= line_to_edit; ++i)lineToWrite = reader.ReadLine();}if (lineToWrite == null)throw new InvalidDataException("行不存在于" + sourceFile);//读取旧文件.string[] lines = File.ReadAllLines(destinationFile);//将新文件写入旧文件.使用 (StreamWriter writer = new StreamWriter(destinationFile)){for (int currentLine = 1; currentLine <=lines.Length; ++currentLine){if (currentLine == line_to_edit){writer.WriteLine(lineToWrite);}别的{writer.WriteLine(lines[currentLine - 1]);}}}}}

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

使用系统;使用 System.IO;课程计划{静态无效主(字符串 [] args){int line_to_edit = 2;string sourceFile = "source.txt";string destinationFile = "target.txt";string tempFile = "target2.txt";//从文件中读取适当的行.字符串 lineToWrite = null;使用 (StreamReader reader = new StreamReader(sourceFile)){for (int i = 1; i <= line_to_edit; ++i)lineToWrite = reader.ReadLine();}if (lineToWrite == null)throw new InvalidDataException("行不存在于" + sourceFile);//从目标文件中读取并写入一个新文件.int line_number = 1;字符串行 = 空;使用 (StreamReader reader = new StreamReader(destinationFile))使用 (StreamWriter writer = new StreamWriter(tempFile)){while ((line = reader.ReadLine()) != null){if (line_number == line_to_edit){writer.WriteLine(lineToWrite);}别的{writer.WriteLine(line);}line_number++;}}//TODO: 在这里删除旧文件并用新文件替换它.}}

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

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

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

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

I have two text files, Source.txt and Target.txt. The source will never be modified and contain N lines of text. So, I want to delete a specific line of text in Target.txt, and replace by an specific line of text from Source.txt, I know what number of line I need, actually is the line number 2, both files.

I haven something like this:

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

using StreamReader reader = new StreamReader(@"C:	arget.xml");
using StreamWriter writer = new StreamWriter(@"C:	arget.xml");

while ((line = reader.ReadLine()) != null)
{
    if (line_number == line_to_edit)
        writer.WriteLine(line);

    line_number++;
}

But when I open the Writer, the target file get erased, it writes the lines, but, when opened, the target file only contains the copied lines, the rest get lost.

What can I do?

解决方案

You can't rewrite a line without rewriting the entire file (unless the lines happen to be the same length). If your files are small then reading the entire target file into memory and then writing it out again might make sense. You can do that like this:

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

If your files are large it would be better to create a new file so that you can read streaming from one file while you write to the other. This means that you don't need to have the whole file in memory at once. You can do that like this:

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.
    }
}

You can afterwards move the file once you are sure that the write operation has succeeded (no excecption was thrown and the writer is closed).

Note that in both cases it is a bit confusing that you are using 1-based indexing for your line numbers. It might make more sense in your code to use 0-based indexing. You can have 1-based index in your user interface to your program if you wish, but convert it to a 0-indexed before sending it further.

Also, a disadvantage of directly overwriting the old file with the new file is that if it fails halfway through then you might permanently lose whatever data wasn't written. By writing to a third file first you only delete the original data after you are sure that you have another (corrected) copy of it, so you can recover the data if the computer crashes halfway through.

A final remark: I noticed that your files had an xml extension. You might want to consider if it makes more sense for you to use an XML parser to modify the contents of the files instead of replacing specific lines.

这篇关于在 C# 中编辑文本文件的特定行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:处理 streamreader 会关闭流吗? 下一篇:我应该为流对象调用 Close() 还是 Dispose()?

相关文章

最新文章