40 votes

Lire à partir d'un fichier en commençant par la fin, similaire à tail.

En C# natif, comment puis-je lire la fin d'un fichier ?

Ceci est pertinent car j'ai besoin de lire un fichier journal, et cela n'a pas de sens de lire 10k, pour lire les 3 dernières lignes.

1 votes

10KB, ce n'est pas beaucoup :)

3 votes

Il est intéressant de noter que si vous avez besoin d'un utilitaire, baretail pour Windows fonctionne très bien.

0 votes

@cfeduke Besoin de regexer la dernière ligne dans une application. Merci quand même.

56voto

Darin Dimitrov Points 528142

Pour lire les 1024 derniers octets :

using (var reader = new StreamReader("foo.txt"))
{
    if (reader.BaseStream.Length > 1024)
    {
        reader.BaseStream.Seek(-1024, SeekOrigin.End);
    }
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

3 votes

Cela fonctionnera-t-il avec les jeux de caractères (tels que UTF-8) qui peuvent utiliser plusieurs octets pour coder un caractère ? Il semble que vous pourriez finir par commencer au milieu d'une séquence de plusieurs octets.

0 votes

Il faudrait tester ce que je vais dire mais, si vous connaissez la taille des caractères (2 octets pour UTF8) de votre chaîne et que vous utilisez un décalage de recherche qui est divisible par ce nombre, cela signifie que debe vous empêcher de lire quoi que ce soit au milieu d'un personnage. Je n'ai jamais vu un flux renvoyer autre chose que le contenu d'un fichier (c'est-à-dire que vous n'obtenez jamais un marqueur de fin de fichier ou d'autres caractères qui ne font pas partie du fichier).

0 votes

Je n'ai pas lu la dernière ligne, mais j'ai lu un certain nombre de lignes plus haut.

11voto

ChaosPandion Points 37025

Peut-être que quelque chose comme ça fonctionnera pour vous :

using (var fs = File.OpenRead(filePath))
{
    fs.Seek(0, SeekOrigin.End);

    int newLines = 0;
    while (newLines < 3)
    {
        fs.Seek(-1, SeekOrigin.Current);
        newLines += fs.ReadByte() == 13 ? 1 : 0; // look for \r
        fs.Seek(-1, SeekOrigin.Current);
    }

    byte[] data = new byte[fs.Length - fs.Position];
    fs.Read(data, 0, data.Length);
}

Notez que cela suppose que \r\n .

1 votes

Si elle est formulée par des doutes dans cette question : stackoverflow.com/questions/4369278/

0 votes

+1 Pour montrer comment on peut vérifier les lignes. Note complémentaire : la vérification de 13 byte-byte suppose un encodage ASCII/UTF8. Si vous ne connaissez pas l'encodage du fichier, cela peut ne pas fonctionner correctement.

5voto

Steve Townsend Points 36948

Le code ci-dessous utilise un accès aléatoire FileStream pour ensemencer un StreamReader à un décalage proche de la fin du fichier, en rejetant la première ligne lue car elle n'est probablement que partielle.

FileStream stream = new FileStream(@"c:\temp\build.txt", 
    FileMode.Open, FileAccess.Read);

stream.Seek(-1024, SeekOrigin.End);     // rewind enough for > 1 line

StreamReader reader = new StreamReader(stream);
reader.ReadLine();      // discard partial line

while (!reader.EndOfStream)
{
    string nextLine = reader.ReadLine();
    Console.WriteLine(nextLine);
}

1voto

Andrew Flanagan Points 3336

Voici une mise en œuvre trouvé rapidement avec Google... J'en ai écrit un moi-même il y a quelque temps mais je n'arrive pas à trouver la source.

1voto

Elaskanator Points 687

Jetez un coup d'œil à ceci réponse à la question correspondante pour lire un fichier de texte en sens inverse. La lecture d'un fichier en sens inverse est très complexe. correctement à cause de trucs comme l'encodage.

1 votes

La seule réponse qui tient compte du codage, qui est un détail assez important.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X