Отредактируйте определенную Строку Текстового файла в C#

У меня есть два текстовых файла, 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++;
        }
    }
}

Но когда я открываю Writer, конечный файл стирается, он пишет строки, но при открытии конечный файл только содержит скопированные строки, остальные теряются.

Что я могу сделать?

29
задан John Odom 30 September 2015 в 01:38
поделиться

4 ответа

Нельзя переписать строку без перезаписи всего файла (если только строки не одинаковой длины). Если ваши файлы маленькие, то чтение всего целевого файла в память, а затем его повторная запись может иметь смысл. Вы можете сделать это следующим образом:

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

Если ваши файлы большие, то лучше создать новый файл, чтобы вы могли читать поток из одного файла во время записи в другой. Это означает, что вам не нужно иметь весь файл в памяти сразу. Вы можете сделать это следующим образом:

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

После этого вы можете переместить файл, как только убедитесь, что операция записи прошла успешно (не было выброшено ни одной выдержки, и запись закрыта).

Обратите внимание, что в обоих случаях немного запутано, что вы используете индексацию на основе 1 для номеров строк. Возможно, в вашем коде имеет смысл использовать индексацию на основе 0. Вы можете использовать индексацию по 1 в вашем пользовательском интерфейсе к программе, если хотите, но конвертируйте ее в 0-индексированную перед дальнейшей отправкой.

Также, недостаток прямой перезаписи старого файла новым файлом заключается в том, что если он не пройдет и половины пути, то вы можете навсегда потерять все данные, которые не были записаны. Записывая сначала в третий файл, вы удаляете исходные данные только после того, как уверены, что у вас есть другая (исправленная) копия, так что вы можете восстановить данные, если компьютер выйдет из строя наполовину.

Заключительное замечание: Я заметил, что ваши файлы имеют расширение xml. Возможно, вы захотите подумать, имеет ли смысл использовать парсер XML для изменения содержимого файлов вместо замены определенных строк.

43
ответ дан 28 November 2019 в 00:46
поделиться

Вам нужно открыть выходной файл для доступа на запись, а не использовать новый StreamReader, который всегда перезаписывает выходной файл.

StreamWriter stm = null;
fi = new FileInfo(@"C:\target.xml");
if (fi.Exists)
   stm = fi.OpenWrite();

Конечно, вам все равно придется искать правильную строку в выходном файле, что будет трудно, так как вы не можете из него читать, так что если вы уже не ЗНАЕТ смещение байта для поиска, то вы, вероятно, действительно хотите получить доступ на чтение/запись.

FileStream stm = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);

с помощью этого потока вы можете читать до тех пор, пока не дойдете до точки, где вы хотите внести изменения, а затем записать. Помните, что вы записываете байты, а не строки, поэтому, чтобы перезаписать строку, вам нужно будет записать то же количество символов, что и строка, которую вы хотите изменить.

.
2
ответ дан 28 November 2019 в 00:46
поделиться

Полагаю, должно сработать следующее (вместо части записи из вашего примера). К сожалению, у меня нет сборочного окружения, так что это из памяти, но я надеюсь, что это поможет

using (var fs = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite)))
        {
            var destinationReader = StreamReader(fs);
            var writer = StreamWriter(fs);
            while ((line = reader.ReadLine()) != null)
            {
              if (line_number == line_to_edit)
                {
                    writer.WriteLine(lineToWrite);
                }
                else
                {
                    destinationReader .ReadLine();
                }
                line_number++;
            }
        }
2
ответ дан 28 November 2019 в 00:46
поделиться

Когда вы создаете StreamWriter, он всегда создает файл с нуля, вам нужно будет создать третий файл, скопировать с целевого и заменить то, что вам нужно, а затем заменить старый. Но так как я вижу, что вам нужна манипуляция XML, вы можете использовать XmlDocument и модифицировать ваш файл с помощью Xpath.

.
3
ответ дан 28 November 2019 в 00:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: