Edite una línea específica de un archivo de texto en C #

Tengo dos archivos de texto, Source.txt y Target.txt. La fuente nunca se modificará y contendrá N líneas de texto. Por lo tanto, quiero eliminar una línea de texto específica en Target.txt y reemplazarla por una línea específica de texto de Source.txt, sé qué número de línea necesito, en realidad es el número de línea 2, ambos archivos.

Tengo algo como esto:

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

Pero cuando abro Writer, el archivo de destino se borra, escribe las líneas, pero cuando se abre, el archivo de destino solo contiene las líneas copiadas, el rest se pierde.

¿Que puedo hacer?

No puede volver a escribir una línea sin volver a escribir todo el archivo (a menos que las líneas tengan la misma longitud). Si sus archivos son pequeños, entonces leer todo el archivo objective en la memoria y luego escribirlo de nuevo puede tener sentido. Puedes hacer eso así:

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

Si sus archivos son grandes, sería mejor crear un nuevo archivo para que pueda leer la transmisión de un archivo mientras escribe en el otro. Esto significa que no necesita tener todo el archivo en la memoria a la vez. Puedes hacer eso así:

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

Posteriormente, puede mover el archivo una vez que esté seguro de que la operación de escritura ha tenido éxito (no se lanzó ninguna excepción y el escritor está cerrado).

Tenga en cuenta que en ambos casos es un poco confuso que esté usando la indexación basada en 1 para sus números de línea. Puede tener más sentido en su código usar la indexación basada en 0. Si lo desea, puede tener un índice basado en 1 en su interfaz de usuario para su progtwig, pero conviértalo a un índice 0 antes de enviarlo más.

Además, la desventaja de sobrescribir directamente el archivo anterior con el nuevo archivo es que si falla a la mitad, puede perder permanentemente los datos que no se escribieron. Al escribir primero en un tercer archivo, usted solo borra los datos originales después de estar seguro de que tiene otra copia (corregida), de modo que puede recuperar los datos si la computadora se bloquea a la mitad.

Una observación final: noté que tus archivos tenían una extensión xml. Es posible que desee considerar si tiene más sentido utilizar un analizador XML para modificar el contenido de los archivos en lugar de reemplazar líneas específicas.

la forma más fácil es:

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

uso:

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

Necesita abrir el archivo de salida para acceso de escritura en lugar de usar un nuevo StreamReader, que siempre sobrescribe el archivo de salida.

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

Por supuesto, igual tendrá que buscar la línea correcta en el archivo de salida, lo cual será difícil ya que no puede leer, por lo que a menos que ya sepa que el byte compensado busca, probablemente quiera leer / escribir acceso.

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

con esta secuencia, puede leer hasta llegar al punto donde desea hacer cambios y luego escribir. Tenga en cuenta que está escribiendo bytes, no líneas, por lo que para sobrescribir una línea necesitará escribir la misma cantidad de caracteres que la línea que desea cambiar.

Cuando crea un StreamWriter , siempre crea un archivo desde cero, tendrá que crear un tercer archivo y copiarlo del objective, reemplazar lo que necesita y luego reemplazar el anterior. Pero como puedo ver lo que necesita es manipulación XML, puede usar XmlDocument y modificar su archivo usando Xpath.

Supongo que lo siguiente debería funcionar (en lugar de la parte del escritor de su ejemplo). Desafortunadamente no tengo un entorno de comstackción así que es de memoria, pero espero que ayude

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