web-dev-qa-db-fra.com

Comment supprimer une ligne d'un fichier texte en C #?

J'ai un problème: comment puis-je supprimer une ligne d'un fichier texte en C #?

37
alinpopescu

Lisez le fichier, supprimez la ligne en mémoire et replacez le contenu dans le fichier (écrasement). Si le fichier est volumineux, vous souhaiterez peut-être le lire ligne par ligne et créer un fichier temporaire, en remplaçant ultérieurement le fichier d'origine.

24
Sascha

Pour les très gros fichiers, je ferais quelque chose comme ça

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

Mise à jour J'ai écrit ceci à l'origine en 2009 et je pensais que cela pourrait être intéressant avec une mise à jour. Aujourd'hui, vous pouvez accomplir ce qui précède en utilisant LINQ et l'exécution différée

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

File.WriteAllLines(tempFile, linesToKeep);

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

Le code ci-dessus est presque identique au premier exemple, lisant ligne par ligne et gardant une quantité minimale de données en mémoire.

Une clause de non-responsabilité pourrait toutefois être utile. Puisque nous parlons de fichiers texte ici, vous auriez très rarement à utiliser le disque comme support de stockage intermédiaire. Si vous ne traitez pas de fichiers journaux très volumineux, la lecture du contenu en mémoire ne devrait pas poser de problème et évitez de traiter le fichier temporaire.

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

Notez que le .ToList est crucial ici pour forcer une exécution immédiate. Notez également que tous les exemples supposent que les fichiers texte sont codés en UTF-8.

68
Markus Olsson

Je suis d'accord avec John Saunders, ce n'est pas vraiment spécifique à C #. Cependant, pour répondre à votre question: vous devez fondamentalement réécrire le fichier. Vous pouvez le faire de deux manières.

  • Lire le fichier entier en mémoire (par exemple avec File.ReadAllLines)
  • Supprimez la ligne incriminée (dans ce cas, il est probablement plus facile de convertir le tableau de chaînes de caractères en List<string> puis de supprimer la ligne).
  • Ecrivez tout le reste des lignes (par exemple, avec File.WriteAllLines) - convertissez éventuellement le List<string> dans un tableau de chaînes à l'aide de ToArray

Cela signifie que vous devez savoir que vous avez assez de mémoire cependant. Une alternative:

  • Ouvrez le fichier d'entrée et un nouveau fichier de sortie (en tant que TextReader/TextWriter, par exemple avec File.OpenText et File.CreateText)
  • Lire une ligne (TextReader.ReadLine) - si vous ne voulez pas la supprimer, écrivez-la dans le fichier de sortie (TextWriter.WriteLine)
  • Lorsque vous avez lu toutes les lignes, fermez le lecteur et le rédacteur (si vous utilisez des instructions using pour les deux, cela se fera automatiquement)
  • Si vous souhaitez remplacer l'entrée par la sortie, supprimez le fichier d'entrée, puis déplacez le fichier de sortie.
19
Jon Skeet

Pour supprimer un élément d'un fichier texte, déplacez d'abord tout le texte dans une liste et supprimez l'élément de votre choix. Ensuite, écrivez le texte stocké dans la liste dans un fichier texte:

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

J'ai étendu ce que Markus Olsson avait suggéré et proposé cette classe qui ajoute plusieurs chaînes de recherche et quelques événements:

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

Usage: 

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");
6
Håvard Fjær

Je voudrais très simplement:

  • Ouvrir le fichier en lecture/écriture
  • Lire/chercher jusqu'au début de la ligne que vous voulez supprimer
  • Définit le pointeur d'écriture sur le pointeur de lecture actuel
  • Lisez jusqu'à la fin de la ligne supprimée et ignorez les délimiteurs de nouvelle ligne (en comptant le nombre de caractères au fur et à mesure, nous l'appellerons nline)
  • Lire octet par octet et écrire chaque octet dans le fichier
  • Lorsque vous avez terminé, tronquez le fichier en (orig_length - nline).
3
Adam Hawes

J'ai écrit une méthode pour supprimer des lignes de fichiers.

Ce programme utilise using System.IO.

Voir mon code:

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());
    }
}
2
Leonhard P.

Pourquoi ne pas utiliser ceci? D'abord, créez un tableau:

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

Recherchez ensuite la ligne à supprimer et remplacez-la par "":

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

Terminé!

0
Marty Brant