47 votes

Trouver efficacement la dernière ligne d'un fichier texte

J'ai besoin d'extraire la dernière ligne d'un certain nombre de fichiers texte très volumineux (plusieurs centaines de mégaoctets) pour obtenir certaines données. Actuellement, j'utilise python pour parcourir toutes les lignes jusqu'à ce que le fichier soit vide, puis je traite la dernière ligne renvoyée, mais je suis certain qu'il existe un moyen plus efficace d'y parvenir.

Quelle est la meilleure façon de récupérer la dernière ligne d'un fichier texte en utilisant Python ?

45voto

sth Points 91594

Ce n'est pas la méthode la plus directe, mais elle est probablement beaucoup plus rapide qu'une simple implémentation en Python :

line = subprocess.check_output(['tail', '-1', filename])

44voto

mick barry Points 545
with open('output.txt', 'r') as f:
    lines = f.read().splitlines()
    last_line = lines[-1]
    print last_line

13voto

Mike DeSimone Points 20059

Utiliser le fichier seek avec un décalage négatif et whence=os.SEEK_END pour lire un bloc à partir de la fin du fichier. Il recherche dans ce bloc le(s) dernier(s) caractère(s) de fin de ligne et saisit tous les caractères qui le suivent. S'il n'y a pas de fin de ligne, revenez en arrière et répétez le processus.

def last_line(in_file, block_size=1024, ignore_ending_newline=False):
    suffix = ""
    in_file.seek(0, os.SEEK_END)
    in_file_length = in_file.tell()
    seek_offset = 0

    while(-seek_offset < in_file_length):
        # Read from end.
        seek_offset -= block_size
        if -seek_offset > in_file_length:
            # Limit if we ran out of file (can't seek backward from start).
            block_size -= -seek_offset - in_file_length
            if block_size == 0:
                break
            seek_offset = -in_file_length
        in_file.seek(seek_offset, os.SEEK_END)
        buf = in_file.read(block_size)

        # Search for line end.
        if ignore_ending_newline and seek_offset == -block_size and buf[-1] == '\n':
            buf = buf[:-1]
        pos = buf.rfind('\n')
        if pos != -1:
            # Found line end.
            return buf[pos+1:] + suffix

        suffix = buf + suffix

    # One-line file.
    return suffix

Notez que cela ne fonctionnera pas sur les systèmes qui ne prennent pas en charge la fonction seek comme stdin ou sockets. Dans ces cas-là, vous êtes obligé de lire tout le contenu (comme dans le cas de l'application tail ).

7voto

rocksportrocker Points 3031

Si vous connaissez la longueur maximale d'une ligne, vous pouvez procéder comme suit

def getLastLine(fname, maxLineLength=80):
    fp=file(fname, "rb")
    fp.seek(-maxLineLength-1, 2) # 2 means "from the end of the file"
    return fp.readlines()[-1]

Cela fonctionne sur ma machine Windows. Mais je ne sais pas ce qui se passe sur d'autres plateformes si vous ouvrez un fichier texte en mode binaire. Le mode binaire est nécessaire si vous voulez utiliser seek().

6voto

Mark Ransom Points 132545

Si vous pouvez choisir une longueur de ligne maximale raisonnable, vous pouvez chercher à atteindre presque la fin du fichier avant de commencer à lire.

myfile.seek(-max_line_length, os.SEEK_END)
line = myfile.readlines()[-1]

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