déterminer le nombre de lignes d'un fichier texte

déterminer le nombre de lignes d'un fichier texte - C++ - Programmation

Marsh Posté le 28-01-2011 à 12:17:07    

Bonjour,
 
je cherche à déterminer le nombre de lignes d'un fichier texte (celui-ci pouvant aller jusqu'à 65000 lignes).
 
Pour l'instant, ma solution consiste à parcourir le fichier en comptant le nombre de caractère '\n', mais je suis perplexe quant à l'implémentation. Voici mon code :
 

Code :
  1. unsigned short cpt = 0; // Décompte du nombre de lignes
  2. std::ifstream ifs ( <fichier> );
  3. if ( ifs.fail() == false ) { // OK le fichier existe
  4.     char buf [ 500 ];
  5.     do {
  6.         ifs.getline ( buf , 500 , '\n' );
  7.         if ( ifs.fail() == false ) {
  8.             ++cpt; // incrémentation du nombre de lignes
  9.         }
  10.     } while ( ifs.eof() == false );
  11. }


Le problème, c'est que je ne connais pas exactement la taille maximum de chaque ligne. Je fixe donc une valeur arbitraire (500) au buffer de lecture en espérant qu'elle suffise dans la plupart des cas.
Si la ligne fait plus de 500 caractères, le "fail bit" est activé. Je sais donc que ma ligne est incomplète et je n'incrémente pas le compteur.
 
Je m'interroge dans le cas où la ligne fait exactement 499 caractères. Que se passe-t-il dans ce cas de figure ?
 
Et indépendamment de mon code, existe-t-il une autre solution plus performante que la mienne ?
 
Merci d'avance !

Reply

Marsh Posté le 28-01-2011 à 12:17:07   

Reply

Marsh Posté le 28-01-2011 à 14:21:25    

Une autre solution est une lecture en mode binaire et de compter les fins de lignes (avec le petit soucis de savoir ce qu'est une fin de ligne : soit CR+LF pour un fichier DOS/Windows, soit LF pour un fichier Unix ou Mac récent, soir CR pour un fichier Mac antérieur à OS X).

Reply

Marsh Posté le 28-01-2011 à 15:52:48    

Effectivement, c'est plus trivial en parcourant le fichier en mode binaire. Disparu, le petit cas tordu...
 
Merci !

Reply

Marsh Posté le 29-01-2011 à 00:39:49    

il suffit de compter le nombre de '\n', car le nombre de '\n' bah c'est le nombre de lignes. A bufferiser quand meme pour optimiser la chose ...
A oui, et si le dernier caractere du fichier est != de '\n' rajouter 1


---------------
Persos D3 :: Yipee-ki-yay motherfucker !!
Reply

Marsh Posté le 29-01-2011 à 10:44:47    

S'il vous plait, spiky31, lisez ce que les autres ont écrit précédemment. Cela peut vous apporter des informations utiles.
 
Par exemple, je disais plus haut, le '\n' que l'on appelle aussi Line Feed ou par ses intiales LF n'est pas forcément présent dans le fichier. On peut avoir seulement des '\r' que l'on appelle aussi Carriage Return ou par ses initiales CR.
 
Et j'avais même oublié un autre cas, qui devient de plus en plus courant qui est celui des fichiers Unicode. Alors, on a deux octets par caractères au lieu d'un seul. Il faut donc tester les doubles octets : 0x00 0x0A, 0x00 0x0D, 0x20 0x28, et 0x20 0x29. Par exemple, dans le cas de l'Unicode, si on ne testait que 0x0A, sans tester 0x00 avant, alors on risquerait de tomber sur un caractère qui ne serait pas un caractère de fin de ligne. On aurait un faux positif.
 
Il y a aussi les cas des variantes de l'Unicode que sont l'UTF8 et de l'UTF16.
 
Sans parler de l'EBCDIC où le LF est codé par 0x15.
 
Bref, cela peut paraître simple, mais cela ne l'est pas tant que cela, surtout si on ne sait pas au début quel type de fichier on va traiter.
 
Voir les articles http://fr.wikipedia.org/wiki/Fin_de_ligne , et sa version en anglaise http://en.wikipedia.org/wiki/Newline , plus complète, qui donne même des cas que je n'ai pas évoqués.

Reply

Marsh Posté le 29-01-2011 à 20:33:33    

J'essayais simplement de résoudre son probleme de taille maximum de ligne, qui en fait n'en est pas un.

shaoyin a écrit :

Le problème, c'est que je ne connais pas exactement la taille maximum de chaque ligne.


Maintenant, ce que tu dis est vrai et meme si le cas de '\r' est facile a prendre en compte, le reste l'est beaucoup moins, c'est clair.
Je n'ai d'ailleurs pas la moindre idée de comment traiter le cas de l'unicode, car même si on parcour le fichier en mode binaire, comment savoir quel encodage a été utilisé ?


---------------
Persos D3 :: Yipee-ki-yay motherfucker !!
Reply

Marsh Posté le 30-01-2011 à 00:15:44    

Reply

Marsh Posté le 30-01-2011 à 01:55:58    


Catégorie: Programmation

 

Sinon pour détecter l'encodage, lis ce topic: http://www.developpez.net/forums/d [...] ier-texte/

 

Visiblement il n'y a pas de méthode fiable à 100%

Message cité 1 fois
Message édité par WiiDS le 30-01-2011 à 02:15:59

---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 30-01-2011 à 09:33:08    

.fail() et .eif() ne font pas ce que vous pensez. Quand elles retournent false, c'est deja trop tard.
 
getline renvoit un bool pour indiquer que la lecture a ete faite correctment.
Je vois pas l'interet de se prendre le groin sur le comptage des /r/n

Reply

Marsh Posté le 31-01-2011 à 09:44:45    

Dans mon cas, pas de souci, chaque caractère est codé sur un octet, mais en effet, l'encodage est à prendre en compte.
 
Je me demande du coup si la solution avec "getline" ne permet pas de s'affranchir de la question de l'encodage ? La doc ne dit rien dessus, mais est-ce que cette fonction arrive à différencier les types de fin de ligne, ou bien ne connait-elle que le caractère de fin de ligne du système où elle est utilisée ?
 
La solution consistant à faire un appel 'system ("wc -l" )' permet effectivement de ne pas se prendre la tête, mais ce n'est clairement pas la solution la plus performante...
 
@ Joel F : ta remarque sur les fonctions eof et fail m'intrigue... Tu penses que j'utilise mal ces fonctions ?

Reply

Marsh Posté le 31-01-2011 à 09:44:45   

Reply

Marsh Posté le 02-02-2011 à 15:36:25    

WiiDS a écrit :


Catégorie: Programmation


 
ben programmer c'est aussi ne pas réinventer la roue tout le temps .... Si ce n'est pas un devoir d'école, il y a surement des solutions qui existent déjà (wc, sed, etc) qu'il pourrait (ré)utiliser.
 
 

Reply

Marsh Posté le 02-02-2011 à 16:03:16    

in_your_phion a écrit :


 
ben programmer c'est aussi ne pas réinventer la roue tout le temps .... Si ce n'est pas un devoir d'école, il y a surement des solutions qui existent déjà (wc, sed, etc) qu'il pourrait (ré)utiliser.
 
 


Certes, tu as parfaitement raison sur le principe, mais il ne faut pas oublier que l'auteur cherche surement à satisfaire sa curiosité personnelle ou simplement effectivement faire un exercice d'école. :jap:


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 02-02-2011 à 16:30:11    

Ce n'est pas un exercice d'école et ce n'est pas non plus pour satisfaire ma curiosité personnelle.
 
Je suis d'accord sur le fait que Linux fournit plein d'outils géniaux en ligne de commande qui font très bien le boulot, mais je ne veux pas que mon programme soit une succession d'appels à "system" ou "exec". Professionnellement, ca fait pas sérieux.
 
Mon programme est en C++, pas en script shell !

Reply

Marsh Posté le 02-02-2011 à 17:26:12    

shaoyin a écrit :

Ce n'est pas un exercice d'école et ce n'est pas non plus pour satisfaire ma curiosité personnelle.
 
Je suis d'accord sur le fait que Linux fournit plein d'outils géniaux en ligne de commande qui font très bien le boulot, mais je ne veux pas que mon programme soit une succession d'appels à "system" ou "exec". Professionnellement, ca fait pas sérieux.
 
Mon programme est en C++, pas en script shell !


... C'est surtout que un appel à wc -l, niveau portabilité c'est 0, byebye Windows et les systèmes Unix qui n'auraient pas wc :D


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed