12
votes

Comment lire des lignes d'un fichier en Python à partir de la fin

J'ai besoin de savoir comment lire des lignes d'un fichier en Python afin de lire la dernière ligne en premier et de continuer à cette manière jusqu'à ce que le curseur atteigne le début du fichier. Des idées?


2 commentaires

Si vous cherchez des "queunes", vous trouverez de bons exemples, tels que: Stackoverflow.com/questions/136168/...


Dupliqué possible de Lire un fichier dans l'ordre inverse à l'aide de Python


5 Réponses :


25
votes

L'approche générale de ce problème, la lecture d'un fichier texte en sens inverse, sage en ligne, peut être résolue par au moins trois méthodes.

Le problème général est que, étant donné que chaque ligne peut avoir une longueur différente, vous ne pouvez pas savoir au préalable où chaque ligne commence dans le fichier, ni combien d'entre eux y sont. Cela signifie que vous devez appliquer une logique sur le problème.

Approche générale n ° 1: Lisez le fichier entier dans la mémoire

Avec cette approche, vous avez simplement lu le fichier entier en mémoire, dans une structure de données qui vous permet ensuite de traiter la liste des lignes en sens inverse. Une pile, une liste doublement liée, ou même un tableau peut faire cela.

Avantages: vraiment facile à mettre en œuvre (probablement intégré à Python pour tout ce que je sais)
inconvénients: utilise beaucoup de mémoire, peut prendre un certain temps pour lire de gros fichiers

Approche générale n ° 2: Lisez le fichier entier, stockez la position des lignes

Avec cette approche, vous avez également lu l'ensemble du fichier une fois, mais au lieu de stocker tout le fichier (tout le texte) en mémoire, vous stockez uniquement les positions binaires dans le fichier où chaque ligne a commencé. Vous pouvez stocker ces positions dans une structure de données similaire comme celle qui stocke les lignes de la première approche.

Situé à lire Line X, vous devez relire la ligne du fichier, à partir du poste que vous avez enregistré pour le début de cette ligne.

Avantages: presque aussi facile à mettre en œuvre que la première approche
inconvénients: peut prendre un certain temps pour lire de gros fichiers

APPROCHE GÉNÉRALE N ° 3: Lisez le fichier en marche arrière et "Figurez-le"

Avec cette approche, vous lirez le bloc-sage de fichier ou similaire, à partir de la fin, et voyez où sont les extrémités. Vous avez essentiellement un tampon, de savoir 4096 octets et traitez la dernière ligne de ce tampon. Lorsque votre traitement, qui doit déplacer une ligne à la fois en arrière dans cette mémoire tampon, vous devez lire une autre valeur tampon de données, de la zone avant le premier tampon que vous lisez et continuez à traiter.

Cette approche est généralement plus compliquée, car vous devez gérer des choses telles que des lignes étant cassées sur deux tampons et que de longues lignes pouvaient même couvrir plus de deux tampons.

C'est cependant celui qui nécessiterait la moindre mémoire, et pour des fichiers vraiment volumineux, cela pourrait également valoir cela pour éviter de lire des gigaoctets d'informations d'abord.

avantages: utilise peu de mémoire, ne vous oblige pas à lire l'ensemble du fichier d'abord inconvénients: beaucoup difficile à mettre en œuvre et à faire raison pour tous les cas d'angle


Il existe de nombreux liens sur le net qui montre comment faire la troisième approche:


2 commentaires

J'avais pensé à faire une approche que la méthode des réadaptions ferait des choses simples ... mais je vais traiter avec de gros fichiers. Je vais devoir réfléchir à la façon de coder l'option 3 ...


J'ai ajouté quelques liens vers le code qui le fait, mais vous ne pouvez en recommander aucun d'entre eux (c'est-à-dire que je ne les ai pas essayés, je ne les recommande donc pas que je ne sera pas , je ne sais tout simplement pas s'ils fonctionnent vraiment.)




1
votes

Un moyen simple est de créer d'abord un fichier inversé temporaire, puis de renverser chaque ligne dans ce fichier.

import os, tempfile

def reverse_file(in_filename, fout, blocksize=1024):
    filesize = os.path.getsize(in_filename)
    fin = open(in_filename, 'rb')
    for i in range(filesize // blocksize, -1, -1):
        fin.seek(i * blocksize)
        data = fin.read(blocksize)
        fout.write(data[::-1])

def enumerate_reverse_lines(in_filename, blocksize=1024):
    fout = tempfile.TemporaryFile()
    reverse_file(in_filename, fout, blocksize=blocksize)
    fout.seek(0)
    for line in fout:
        yield line[::-1]


0 commentaires

1
votes

Cette solution est plus simple que toutes les autres que j'ai vues. XXX PRE>

Exemple d'utilisation: P>

for line in xreadlines_reverse(open("whatever.txt")):
    do_stuff(line)


1 commentaires

Cela ne gère pas correctement les fichiers sur lesquels on ne peut pas chercher. Sur mon système, sys.stsdin.seek (x, y) ne produit aucune erreur et sys.stsdin.tell () renvoie un entier, ce qui rend difficile la distinction si ne pas chercher est supporté. La meilleure solution est probablement de tenter un OS.LSek .



4
votes

Vous pouvez également utiliser le module Python File_read_backwards. Il serait lu à une manière efficace de la mémoire. Il fonctionne avec Python 2.7 et 3.

Il prend en charge "UTF-8", "Latin-1" et "ASCII" codant. Il fonctionnera avec "\ r", "\ n" et "\ r \ n" comme de nouvelles lignes.

après l'installation, via PIP Install File_read_backwards (V1. 2.1), vous pouvez lire l'intégralité du fichier à l'envers (ligne-wise) via: xxx

Documentation supplémentaire peut être trouvé sur http://file-read-backwards.readthedocs.io/en/latest/readme.html


0 commentaires