Obtenir le nombre de lignes d'un fichier texte nécessite classiquement de les lire toutes pour les compter.
On va utiliser un autre principe: lire le fichier par blocs binaires, et compter le nombre de caractères de fin de ligne ('\n' par défaut).
def nblignes(nf, fdl='\n', tbuf=16384): """Compte le nombre de lignes du fichier nf""" c = 0 f = open(nf, 'rb') while True: buf = None buf = f.read(tbuf) if len(buf)==0: break c += buf.count(fdl) f.seek(-1, 2) car = f.read(1) if car != fdl: c += 1 f.close() return c
Il y a une petite subtilité: il est possible que la dernière ligne de texte ne soit pas terminée par un caractère de fin de ligne. Auquel cas, dans un éditeur de texte, le curseur resterait à la fin de la dernière ligne en refusant de passer à la ligne vide suivante. Mais comme c'est tout de même une ligne de texte, il faut la compter. C'est ce que fait la dernière partie du code commençant par f.seek(-1, 2).
Application. Fabriquons un fichier texte de 50000 lignes:
nf = 'test.txt' f = open(nf, 'w') for i in xrange(0,50000): x = "%d" % (i) f.write(x + '\n') f.close
Et comptons le nombre de ligne de ce fichier:
print nblignes(nf) 50000
Et si on fait en sorte que la dernière ligne ne comporte pas de fin de ligne:
nf = 'test.txt' f = open(nf, 'w') for i in xrange(0,49999): x = "%d" % (i) f.write(x + '\n') x = "%d" % (49999) f.write(x) f.close
Le comptage du nombre de lignes donne le même résultat:
print nblignes(nf) 50000
Est-ce que c'est rapide? Assez, oui:
Sur un fichier de 1000000 (1 million) de lignes et 7,7 Mo, le nombre de lignes est obtenu en 10 fois moins de temps par cette méthode par rapport à la méthode de lecture texte de toutes les lignes. Et en plus, on consomme beaucoup moins de place mémoire puisque les blocs lus prennent la même place mémoire (on le vérifie par id(buf)) et donc ne la fragmente pas.
Amusez-vous bien!