Редактирование определенной строки текстового файла в 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, целевой файл стирается, он записывает строки, но при открытии целевой файл содержит только скопированные строки, остальные теряются.

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

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

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

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

 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-парсер для изменения содержимого файлов вместо замены определенных строк.

самый простой способ:

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

Применение :

 lineChanger("new content for this line" , "sample.text" , 34); 

Вам нужно открыть выходной файл для доступа к записи, а не использовать новый 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); 

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

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

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

 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++; } } 
  • Почему streamи C ++ используют char вместо unsigned char?
  • Java: как определить правильную кодировку кодировки streamа
  • одновременное чтение и запись файла в C #
  • Interesting Posts

    Правильный, идиоматический способ использования настраиваемых шаблонов редактора с моделями IEnumerable в ASP.NET MVC

    jQuery как найти элемент на основе значения атрибута данных?

    Отключить экранную клавиатуру в Windows 7

    Как отключить антивирус Symantec Endpoint Protection?

    создать макет chatView в android

    Плагин Adobe Reader для браузера Firefox ворует прокрутку сенсорной панели

    Шрифт Monaco не сглажен в некоторых приложениях GTK

    Кэширование в современных браузерах отстой, почему и как исправить?

    Включение / выключение питания 3 раза перед правильной загрузкой с холодного запуска, никаких других проблем (новая система)

    Android Facebook 4.0 SDK Как получить электронную почту, дату рождения и пол пользователя

    Использование двухэлементных разъемов (один для LAN, один для WAN)

    Компактные файлы в смежной области на диске

    Перемещение проекта в другую папку в Eclipse

    Преобразовать serial.read () в полезную строку с помощью Arduino?

    Как определить, что заставляет Chrome показывать диалог «Aw, Snap»

    Давайте будем гением компьютера.