10
votes

Changeant std :: endl à mettre Cr + LF au lieu de lf

J'écris un programme sur une plate-forme Linux générant des fichiers texte qui seront visionnés, inévitablement, une plate-forme Windows.

En ce moment, passe std :: endl dans un ostream génère le personnage CR uniquement pour les lignes neuves. Naturellement, ces fichiers texte ont l'air faux dans le bloc-notes MS.

  1. Y a-t-il un moyen de changer std :: endl tel qu'il utilise CR + LF pour la nouvelle ligne au lieu de LF?
  2. Je sais que je pouvais écrire mon propre manipulateur personnalisé, comme win_endl , pour générer mes propres nouvelles lignes, mais j'utilise le symbole std :: endl dans beaucoup d'endroits et comme de nombreux programmeurs, ont tendance à faire ce qui nécessite le moins de travail possible. Puis-je simplement surcharger std :: endl pour produire CR + LF ou est-ce une idée muette pour la maintenabilité?

    nb: j'ai vérifié Cette question , mais il demande à propos d'aller dans l'autre sens et la réponse acceptée semble plutôt incomplète.


5 commentaires

Une autre option consiste à utiliser un outil sur Windows qui sait comment traiter les nouvelles lignes de style UNIX (c'est-à-dire n'importe quel éditeur autre que le Bloc-notes) ou utiliser un outil convertit les fins de la ligne (communément appelées UNIX2DOS.EXE ou quelque chose).


@Michael Burr - Bonne idée, mais difficile à soutenir avec notre clientèle est ma réaction de gut.


Il n'est pas nécessaire de fonctionner sur la machine à la clientèle - il y a des filtres qui feront la même chose sur une boîte Unix. Vous pouvez avoir les fichiers de sortie produites par votre programme actuel exécuté via le filtre avant de les emballer pour la distribution au client. Cela semble hacky, mais je pense que cela pourrait être moins hacky que de mordre avec le C ++ Streamio (et c'est probablement beaucoup moins de travail).


@Michael Burr - Votre deuxième point est également une bonne idée, et celui que j'ai pensé à un peu. Peut-être que je dois y penser un peu plus. La principale raison pour laquelle j'ai abouti à cette idée était de conserver le "filtrage" dans mon application C ++ au lieu d'appeler un programme externe sur le fichier résultant. Transformez vos commentaires en une réponse et je vais vous donner un +1.


Le problème est que vous avez utilisé std :: endl , que vous ne devrait pas car dans de nombreuses implémentations, la sortie standard est tamponnée à la ligne tamponnée et écrit '\ n' Permis de toute façon, à moins que STD :: iOS :: Sync_with_stdio (Faux) a été exécuté. Dans ces situations, l'ENDL inutile ne dégrade que les performances de la sortie de fichier, pas de sortie standard


5 Réponses :


12
votes

std :: endl est fondamentalement: xxx

alors utilisez simplement "\ r \ n" et omettez le rinçage. C'est plus rapide de cette façon, aussi!

du fichier d'en-tête Ostream sur endl:

Ce manipulateur est souvent utilisé à tort quand une nouvelle ligne simple est souhaitée, conduisant à une mauvaise performance tampon.


4 commentaires

Si vous faites cela, n'oubliez pas d'ouvrir le flux en mode binaire - sinon, si vous portez déjà ce code à Windows, vous obtiendrez \ r \ r \ n dans la sortie (puisque \ n lui-même sera étendu à \ r \ n pour un flux de texte).


Cela ne sera pas porté à Windows, je ne pense pas. Nous ne pouvions probablement pas gérer la licence. MDR


+1 - Good Info sur le manipulateur endl. Methinks Je l'utiliserai moins souvent maintenant.


Si votre fichier est en mode texte. Le caractère '\ n' est traduit en une séquence de fin de ligne spécifique à la plate-forme lorsque vous écrivez dans le fichier. Et la séquence de fin de ligne est traduite en '\ n' lorsque vous lisez dans le fichier.



2
votes

Vous ne devriez pas utiliser \ r \ n. Il suffit d'utiliser \ n, mais ouvrez ensuite le flux en mode "Texte", qui ne fera pas la conversion pour vous. Vous ne vous souciez pas de la plate-forme inter-plate-forme, mais c'est la manière officielle de le faire.

De cette façon, le même code va cracher \ n sur UNIX, \ r \ n sous Windows et \ R sur Mac.


5 commentaires

Le programme qui génère le fichier texte toujours sera exécuté sur une plate-forme Linux, et il ne sera pas exécuté sur Win / Mac du tout. Les machines qui lisent le fichier texte exécuteront des systèmes de consommation (Windows, Mac, Linux).


Le problème est le Bloc-notes, aussi simple que l'application, ne respecte pas les autres nouvelles lignes. Autres plateformes Les éditeurs de texte par défaut font, il est donc obligé de le faire \ r \ n , de sorte que Windows joue également bien.


+1 pour me rappeler que nos clients pourraient être en cours d'exécution sur Macs. Je ne devrais pas oublier les macs.


\ r comme eol a été utilisé sur Mac OS 9, OS X utilise \ n.


De plus, si vous avez un fichier texte avec \ n pour les terminaisons de ligne, vous pouvez facilement afficher et modifier ce fichier si vous utilisez WordPad, qui est livré avec toutes les fenêtres. Vous ne feriez pas cela sur votre propre ordinateur car j'espère que vous auriez quelque chose comme le NOTEPAD ++ installé. Mais si vous courez sur un ordinateur arbitraire, il est agréable de connaître le tour de Wordpad.



10
votes

Ouverture d'un fichier en mode texte doit causer std :: endl à convertir en ligne appropriée terminant pour votre plate-forme. Votre problème est que la nouvelle ligne est appropriée pour votre plate-forme, mais les fichiers que vous créez ne sont pas destinés à votre plate-forme.

Je ne sais pas comment vous envisagez de surcharger ou de changer endl et de changer son comportement serait certainement surprenant pour tout développeur nouveau dans votre projet. Je vous recommanderais de passer à Win_endl (devrait être une simple recherche-et-remplacement) ou peut-être passer d'une standard ostream à un BOOST.IASTREAMS Filtrage Stream Pour faire la conversion pour vous.


2 commentaires

+1 pour la solution Boost.iostreams. Plus spécifiquement, utilisez un newline_filter: boost.org/doc/libs/1_40_0/libs/iostreams/doc/...


Aurait disparu de cet itinéraire (toujours peut si la macro devient fastidieuse à maintenir) mais nous avons un système gobineux pour obtenir une augmentation des pkgs au travail, et j'aurais dû bugement à quelqu'un de passer à travers une gigmarole pour l'obtenir à ma console.



7
votes

Windows Notepad est à peu près le programme Windows, vous trouverez que cela ne gère pas correctement les fichiers LF uniquement. Presque tout le reste (y compris WordPad) gère uniquement des fichiers LF uniquement.

Ce problème est un bogue dans le bloc-notes.


4 commentaires

Nos clients auront probablement double de double-cliquer sur le fichier. Nous serons donc à la merci de toute application se sont inscrites au moment de leur machine. Probablement le bloc-notes par défaut sur Windows.


Si vous devez créer des fichiers avec des terminaisons de ligne CRLF, exécutez le ou les fichiers de sortie via un filtre indépendant de votre programme lui-même. Vous pouvez trouver ce type de filtre facilement, rechercher unix2dos ou quelque chose comme ça. Cela conservera cette logique spécifique à la plate-forme de votre programme.


Cependant, n'oubliez pas que les programmes UNIX sont généralement aussi impératifs de la lecture de fichiers texte contenant des terminaisons de ligne "\ r \ n" - de mon expérience limitée avec UNIX, qui semble être une question plus vaste (en termes de Nombre de programmes qui ne traitent pas bien avec les fins de ligne non indigènes).


Enfin, plus. La version Windows 10 du Bloc-notes peut gérer les fins de la ligne. Quel progrès! Windows 10 est les meilleures fenêtres que nous ayons jamais eues.



0
votes

Voici ma solution au problème. C'est un peu une mash-up de toutes les informations fournies dans les réponses:

  1. J'ai créé une macro dans un fichier win_endl.h pour la nouvelle ligne que je voulais: XXX

  2. Puis j'ai fait une recherche-and-remplacer: XXX

    et assura tous mes fichiers inclus win_endl.h .


1 commentaires

Ce n'est vraiment pas une solution si vous utilisez du mode texte, car "\ n" est traduit en une séquence de fin de ligne spécifique à la plate-forme. Sur Linux, "\ n" est une carte directement sur le caractère LF. Mais si vous avez rencontré ce code sur Windows, vous verriez CR-CR-LF car "\ n" mappe sur CR-LF sous Windows.