Lisez-vous le fichier dans BINAIRE ou en TEXTE mode ? En TEXTE la paire retour chariot/saut de ligne, CRLF est interprété comme TEXTE fin de ligne, ou caractère de fin de ligne, mais en BINAIRE vous n'obtenez que UN octet par octet, ce qui signifie que l'un ou l'autre caractère MUST est ignorée et laissée dans la mémoire tampon pour être récupérée comme un autre octet ! Le retour du chariot signifie, dans une machine à écrire, que le chariot de la machine à écrire, dans lequel se trouve le bras d'impression, a atteint le bord droit du papier et est ramené au bord gauche. Il s'agit d'un modèle très mécanique, celui de la machine à écrire mécanique. L'avance de la ligne signifie que le rouleau de papier est légèrement tourné vers le haut afin que le papier soit en position pour commencer une autre ligne de frappe. Pour autant que je me souvienne, l'un des chiffres les plus bas de l'ASCII signifie qu'il faut se déplacer vers la droite d'un caractère sans taper, le caractère mort, et bien sûr \b signifie retour en arrière : déplacer la voiture d'un caractère vers l'arrière. De cette façon, vous pouvez ajouter des effets spéciaux, comme le soulignement (type underscore), le barré (type minus), des accents différents approximatifs, l'annulation (type X), sans avoir besoin d'un clavier étendu, simplement en ajustant la position de la voiture le long de la ligne avant d'entrer le saut de ligne. Il est donc possible d'utiliser des tensions ASCII de la taille d'un octet pour contrôler automatiquement une machine à écrire sans ordinateur intermédiaire. Lorsque la machine à écrire automatique est introduite, AUTOMATIQUE signifie qu'une fois que vous avez atteint le bord le plus éloigné de la feuille, la voiture est renvoyée à gauche. ET le saut de ligne appliqué, c'est-à-dire que le wagon est supposé être renvoyé automatiquement au fur et à mesure que le rouleau se déplace vers le haut ! Vous n'avez donc pas besoin des deux caractères de contrôle, mais d'un seul, le caractère \n , nouvelle ligne ou saut de ligne.
Cela n'a rien à voir avec la programmation, mais l'ASCII est plus ancien et il semble que certaines personnes n'aient pas réfléchi lorsqu'elles ont commencé à faire du texte ! La plateforme UNIX suppose une machine à écrire automatique électrique ; le modèle Windows est plus complet et permet de contrôler des machines mécaniques, bien que certains caractères de contrôle deviennent de moins en moins utiles dans les ordinateurs, comme le caractère cloche, 0x07 si je me souviens bien... Certains textes oubliés ont dû être saisis à l'origine avec des caractères de contrôle pour des machines à écrire à commande électrique, ce qui a perpétué le modèle...
En fait, la variante correcte consisterait à inclure simplement l'élément \r , saut de ligne, le retour chariot n'étant pas nécessaire, c'est-à-dire automatique, donc :
char c;
ifstream is;
is.open("",ios::binary);
...
is.getline(buffer, bufsize, '\r');
//ignore following \n or restore the buffer data
if ((c=is.get())!='\n') is.rdbuf()->sputbackc(c);
...
serait la manière la plus correcte de traiter tous les types de fichiers. Il convient toutefois de noter que \n en TEXTE est en fait la paire d'octets 0x0d 0x0a, mais 0x0d IS juste \r : \n comprend \r en TEXTE mais pas en mode BINAIRE Así que \n y \r\n sont équivalents... ou devraient l'être. Il s'agit en fait d'une confusion très fondamentale dans l'industrie, d'une inertie typique de l'industrie, puisque la convention est de parler de CRLF, dans TOUTES les plateformes, puis de tomber dans des interprétations binaires différentes. Strictement parlant, les fichiers comprenant UNIQUEMENT 0x0d (retour chariot) comme étant \n (CRLF ou saut de ligne), sont malformés en TEXTE (machine à écrire : il suffit de retourner la voiture et de tout barrer...), et sont un format binaire non orienté vers la ligne (soit \r o \r\n c'est-à-dire orienté vers la ligne) et n'est donc pas censé être lu comme du texte ! Le code devrait échouer, peut-être avec un message de l'utilisateur. Cela ne dépend pas seulement du système d'exploitation, mais aussi de l'implémentation de la bibliothèque C, ce qui ajoute à la confusion et aux variations possibles... (en particulier pour les couches de traduction UNICODE transparentes, qui ajoutent un autre point d'articulation pour des variations déroutantes).
Le problème de l'extrait de code précédent (machine à écrire mécanique) est qu'il est très inefficace s'il n'y a pas de \n caractères après \r (texte de la machine à écrire automatique). Ensuite, il suppose également BINAIRE où la bibliothèque C est forcée d'ignorer les interprétations de texte (locale) et de donner les octets purs. Il ne devrait pas y avoir de différence entre les deux modes en ce qui concerne les caractères de texte proprement dits, mais seulement les caractères de contrôle. BINAIRE est meilleur que TEXTE mode. Cette solution est efficace pour BINAIRE Le logiciel est inefficace pour les fichiers texte typiques du système d'exploitation Windows, indépendamment des variations de la bibliothèque C, et inefficace pour les formats de texte d'autres plates-formes (y compris les traductions de sites web en texte). Si vous vous souciez de l'efficacité, la solution consiste à utiliser un pointeur de fonction, à effectuer un test pour le mode \r vs \r\n Sélectionnez ensuite le meilleur code utilisateur getline dans le pointeur et invoquez-le à partir de celui-ci.
Par ailleurs, je me souviens avoir trouvé des \r\r\n ce qui se traduit par un texte à deux lignes, comme l'exigent encore certains consommateurs de textes imprimés.
2 votes
\n signifie nouvelle ligne, quelle que soit la manière dont elle est présentée dans le système d'exploitation actuel. La bibliothèque s'en charge. Mais pour que cela fonctionne, un programme compilé sous Windows doit lire les fichiers texte de Windows, un programme compilé sous Unix, les fichiers texte d'Unix, etc.
1 votes
@George, même si je compile sur une machine Linux, j'utilise parfois des fichiers texte provenant d'une machine Windows. Je vais peut-être publier mon logiciel (un petit outil d'analyse de réseau), et je veux pouvoir dire aux utilisateurs qu'ils peuvent fournir presque n'importe quel type de fichier texte (de type ASCII).
3 votes
Petit testcase qui démontre votre problème .
1 votes
Notez que if(f.good()) ne fait pas ce que vous semblez penser qu'il fait.
0 votes
Merci @Neil, je suis tombé dans le panneau alors que j'ai tout vérifié il y a quelques jours ! Je l'ai bien compris à l'époque. Je pense que je me suis laissé aller à supposer que
f.good()
devrait être le contraire def.fail()
.0 votes
@LightningRacisinObrit Arg, ideone.com J'étais en train d'essayer de trouver un exemple en ligne de ceci. Pouvez-vous me raconter ce que vous aviez fait il y a 4 ans ?
1 votes
@JonathanMee : C'était peut-être comme cette . Peut-être.