2009-03-21 62 views
31

Tengo un problema: ¿cómo puedo eliminar una línea de un archivo de texto en C#?¿Cómo eliminar una línea de un archivo de texto en C#?

+0

Él/ella significa cómo eliminarlo mediante programación, supongo. – splattne

+35

@ John Saunders: ¿Es tan difícil de entender que OP desea eliminar una línea de un archivo de texto usando C#? ¿Cómo es eso no específico? Seamos un poco más acogedores con los novatos. –

Respuesta

24

Lea el archivo, elimine la línea en la memoria y vuelva a colocar el contenido en el archivo (sobrescritura). Si el archivo es grande, puede leerlo línea por línea y crear un archivo temporal, reemplazando luego el original.

17

Estoy de acuerdo con John Saunders, esto no es realmente específico de C#. Sin embargo, para responder a su pregunta: básicamente necesita volver a escribir el archivo. hay dos maneras de hacer esto.

  • leer todo el archivo en la memoria (por ejemplo, con File.ReadAllLines)
  • Retire la línea en cuestión (en este caso, es probable que sea más fácil de convertir la matriz de cadenas en una List<string> a continuación, quitar la línea)
  • escribir todas las resto de las líneas de fondo (por ejemplo, con File.WriteAllLines) - potencialmente convertir el List<string> en una matriz de cadenas de nuevo usando ToArray

eso significa que usted tiene que saber que usted tiene suficiente memoria aunque. Una alternativa:

  • tanto el archivo de entrada abierta y un nuevo archivo de producto (como TextReader/TextWriter, por ejemplo, con File.OpenText y File.CreateText)
  • leer una línea (TextReader.ReadLine) - si no quiere eliminar ella, escribir al archivo de salida (TextWriter.WriteLine)
  • Cuando usted ha leído todas las líneas, cerca tanto el lector como el escritor (si utiliza using declaraciones por tanto, que esto sucederá automáticamente)
  • Si desea para reemplazar la entrada con la salida, deletreó e el archivo de entrada y luego mueva el archivo de salida a su lugar.
+0

Estoy en la misma situación en la que tengo que eliminar el encabezado de un archivo y anexarlo a otro archivo. En Windows, si utilizo funciones de DOS a través de C#, ¿cree que sería una ganancia de rendimiento? Aquí está el comando ... > MORE +1 "sourcefilepath"> "targetFilePath" –

+0

@ImranAmjad: No lo sé, pero no parece que sea difícil de probar. ¿Es esta una parte particularmente crítica del rendimiento de su flujo de trabajo? –

+0

Sí, el tamaño del archivo puede ser más de la mitad de un GB y tengo que hacerlo con frecuencia. Hacerlo desde los comandos de DOS toma toda la carga y estoy seguro de que es más rápido ya que los comandos dos omiten todas las capas del sistema operativo. No estoy seguro acerca de gran parte de los internos. También ahorra muchas líneas de código, pero la legibilidad del código se ve comprometida para algunas personas. –

63

Para mismos archivos de gran tamaño que me gustaría hacer algo como esto

string tempFile = Path.GetTempFileName(); 

using(var sr = new StreamReader("file.txt")) 
using(var sw = new StreamWriter(tempFile)) 
{ 
    string line; 

    while((line = sr.ReadLine()) != null) 
    { 
     if(line != "removeme") 
      sw.WriteLine(line); 
    } 
} 

File.Delete("file.txt"); 
File.Move(tempFile, "file.txt"); 

actualización Originalmente escribí esta de nuevo en 2009 y pensé que podría ser interesante con una actualización. Hoy en día se podría lograr lo anterior usando LINQ and deferred execution

var tempFile = Path.GetTempFileName(); 
var linesToKeep = File.ReadLines(fileName).Where(l => l != "removeme"); 

File.WriteAllLines(tempFile, linesToKeep); 

File.Delete(fileName); 
File.Move(tempFile, fileName); 

El código anterior es casi exactamente el mismo que el primer ejemplo, la lectura línea por línea y manteniendo una cantidad mínima de datos en la memoria.

Sin embargo, un descargo de responsabilidad podría estar en orden. Ya que estamos hablando de archivos de texto aquí, rara vez tendrá que usar el disco como medio de almacenamiento intermedio. Si no se trata de archivos de registro muy grandes, no debería haber problemas para leer los contenidos en la memoria y evitar tener que lidiar con el archivo temporal.

File.WriteAllLines(fileName, 
    File.ReadLines(fileName).Where(l => l != "removeme").ToList()); 

Tenga en cuenta que El .ToList es crucial aquí para forzar la ejecución inmediata. También tenga en cuenta que todos los ejemplos asumen que los archivos de texto están codificados en UTF-8.

2

que había muy simple:

  • Abra el archivo para lectura/escritura
  • lectura/buscan a través de él hasta el inicio de la línea que desea borrar
  • Establecer el puntero de escritura en el puntero de lectura actual
  • Lea hasta el final de la línea que estamos eliminando y omita los delimitadores de nueva línea (contando el número de caracteres a medida que avanzamos, lo llamaremos nline)
  • Leer byte a byte y escribe cada byte en el archivo
  • Cuando termine de truncar el archivo a (orig_length - nline).
5

extendí lo sugiere Markus Olsson, y se acercó con esta clase que añade varias cadenas de búsqueda y un par de evento:

public static class TextLineRemover 
{ 
    public static void RemoveTextLines(IList<string> linesToRemove, string filename, string tempFilename) 
    { 
     // Initial values 
     int lineNumber = 0; 
     int linesRemoved = 0; 
     DateTime startTime = DateTime.Now; 

     // Read file 
     using (var sr = new StreamReader(filename)) 
     { 
      // Write new file 
      using (var sw = new StreamWriter(tempFilename)) 
      { 
       // Read lines 
       string line; 
       while ((line = sr.ReadLine()) != null) 
       { 
        lineNumber++; 
        // Look for text to remove 
        if (!ContainsString(line, linesToRemove)) 
        { 
         // Keep lines that does not match 
         sw.WriteLine(line); 
        } 
        else 
        { 
         // Ignore lines that DO match 
         linesRemoved++; 
         InvokeOnRemovedLine(new RemovedLineArgs { RemovedLine = line, RemovedLineNumber = lineNumber}); 
        } 
       } 
      } 
     } 
     // Delete original file 
     File.Delete(filename); 

     // ... and put the temp file in its place. 
     File.Move(tempFilename, filename); 

     // Final calculations 
     DateTime endTime = DateTime.Now; 
     InvokeOnFinished(new FinishedArgs {LinesRemoved = linesRemoved, TotalLines = lineNumber, TotalTime = endTime.Subtract(startTime)}); 
    } 

    private static bool ContainsString(string line, IEnumerable<string> linesToRemove) 
    { 
     foreach (var lineToRemove in linesToRemove) 
     { 
      if(line.Contains(lineToRemove)) 
       return true; 
     } 
     return false; 
    } 

    public static event RemovedLine OnRemovedLine; 
    public static event Finished OnFinished; 

    public static void InvokeOnFinished(FinishedArgs args) 
    { 
     Finished handler = OnFinished; 
     if (handler != null) handler(null, args); 
    } 

    public static void InvokeOnRemovedLine(RemovedLineArgs args) 
    { 
     RemovedLine handler = OnRemovedLine; 
     if (handler != null) handler(null, args); 
    } 
} 

public delegate void Finished(object sender, FinishedArgs args); 

public class FinishedArgs 
{ 
    public int TotalLines { get; set; } 
    public int LinesRemoved { get; set; } 
    public TimeSpan TotalTime { get; set; } 
} 

public delegate void RemovedLine(object sender, RemovedLineArgs args); 

public class RemovedLineArgs 
{ 
    public string RemovedLine { get; set; } 
    public int RemovedLineNumber { get; set; } 
} 

Uso:

 TextLineRemover.OnRemovedLine += (o, removedLineArgs) => Console.WriteLine(string.Format("Removed \"{0}\" at line {1}", removedLineArgs.RemovedLine, removedLineArgs.RemovedLineNumber)); 
     TextLineRemover.OnFinished += (o, finishedArgs) => Console.WriteLine(string.Format("{0} of {1} lines removed. Time used: {2}", finishedArgs.LinesRemoved, finishedArgs.TotalLines, finishedArgs.TotalTime.ToString())); 
     TextLineRemover.RemoveTextLines(new List<string> { "aaa", "bbb" }, fileName, fileName + ".tmp"); 
5

Para Quitar elemento de archivo de texto, primero mueva todo el texto a una lista y elimine el elemento que desee. Luego escriba el texto almacenado en la lista en el archivo de texto

List<string> quotelist=File.ReadAllLines(filename).ToList(); 
      string firstItem= quotelist[0]; 
      quotelist.RemoveAt(0); 
      File.WriteAllLines(filename, quotelist.ToArray()); 
      return firstItem; 
+1

¿Qué tal para "la otra mitad" (está bien, el otro 0.05 por ciento) que no tiene ReadAllLines() o WriteAllLines() en su versión de .NET? –

2

Hola chicos, escribí un método para eliminar líneas de los archivos. Este programa utiliza using System.IO

Ver mi código:

void File_DeleteLine(int Line, string Path) 
    { 
     StringBuilder sb = new StringBuilder(); 
     using (StreamReader sr = new StreamReader(Path)) 
     { 
      int Countup = 0; 
      while (!sr.EndOfStream) 
      { 
       Countup++; 
       if (Countup != Line) 
       { 
        using (StringWriter sw = new StringWriter(sb)) 
        { 
         sw.WriteLine(sr.ReadLine()); 
        } 
       } 
       else 
       { 
        sr.ReadLine(); 
       } 
      } 
     } 
     using (StreamWriter sw = new StreamWriter(Path)) 
     { 
      sw.Write(sb.ToString()); 
     } 
    } 
0

¿Por qué no se puede usar esto? En primer lugar, crear una matriz:

string[] lines = File.ReadAllLines(openFileDialog1.FileName); 

A continuación, busque la línea que necesita para eliminar y reemplazarlo con "":

lines[x].Replace(lines[x], ""); 

Hecho!

+1

Esto no * elimina * la línea del archivo, todo lo que hace es hacer que la línea 'x' esté vacía. Por lo tanto, si estuvieras haciendo esto mucho, terminarías con un montón de declaraciones vacías en el archivo, lo que podría arruinar los índices. – carefulnow1

Cuestiones relacionadas