Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1252 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Ecriture/Lecture de fichier binaire (ios::binary) avec << et >>

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Ecriture/Lecture de fichier binaire (ios::binary) avec << et >>

n°854658
nathan_g
Posté le 21-09-2004 à 11:08:50  profilanswer
 

Bonjour,
 
Un petit souci ...
 
Je souhaiterais écrire un fichier en binaire en C++. J'ouvre mon fichier "Data.d" et j'écris un entier par :
 
char* ident = "Data.d";
ofstream ofs;
int numb = 1234;
 
ofs.open(ident,ios::out|ios::binary);
 
ofs.write((int *) &numb,sizeof(int));
 
Apparemment, la valeur est correctement enregistrée car une opération de lecture en binaire par la commande ifs.read(...) (le fichier "Data.d" est rouvert et lu par un ifstream) réussit. Cependant, j'avais souhaité faire plus simple avec la commande :
 
ofs << numb;
 
en remplacement de la ligne  
 
ofs.write((int *) &numb,sizeof(int));
 
Or, cette opération me donne la forte impression de correspondre à une écriture en ASCII (notamment car la commande more permet la relecture du fichier qui contient la valeur), alors même que le fichier "Data.d" doit être écrit en binaire, ce qui est expliciement spécifié dans la ligne :
 
ofs.open(ident,ios::out|ios::binary);
 
D'où vient le problème. Pourquoi une écriture par la commande << ne permet t'elle pas une écriture du fichier en binaire ? Est-il possible de se passer de la commande (loure à mon avis) " ofs.write((int *) &numb,sizeof(int)); " pour forcer l'écriture en binaire ?
 
 
 

mood
Publicité
Posté le 21-09-2004 à 11:08:50  profilanswer
 

n°854669
nathan_g
Posté le 21-09-2004 à 11:17:50  profilanswer
 

Bon ...
 
Il semble qu'il y ait eu une mauvaise lecture de certains caractères. Les petites têtes ont replacés ce que j'avais tapé. Il fallait lire la constante d'ouverture en écriture d'un fichier, accompagné du mode d'ouverture binaire :
 
ios :: out|ios :: binary
 
J'ai mis un espace entre les :: et les ios, out et binary pour que ça puisse passer (en espérant que ça marche !).
 
E

n°854679
Taz
bisounours-codeur
Posté le 21-09-2004 à 11:32:59  profilanswer
 

c'est quoi ces cast à la con ?
pourquoi t'utilise pas le constructeur ?

n°854705
nathan_g
Posté le 21-09-2004 à 11:47:19  profilanswer
 

>> c'est quoi ces cast à la con ?  
>> pourquoi t'utilise pas le constructeur ?
 
Comme j'ai déja du le dire, je suis débutant en C++ (surtout par rapport aux membres les plus actifs de ce forum). De toutes façons, il y a, en fait, bcp plus de choses à lire que ça, donc un constructeur seul est peutêtre trop simple.
 
En fait ce qui me pose problème, c'est déja ce choix de commande pour écrire un fichier binaire !  
 

n°854721
Taz
bisounours-codeur
Posté le 21-09-2004 à 12:01:59  profilanswer
 

ben si tu fais
 
 
ifstream f;
 
 
et 100 lignes plus bas que tu appelles open, y a un problème
 
 
 
quand au reste, c'est pourtant simple : y a deux sémantiques différentes, donc deux façons de coder. D'un côté les << et >> surchargés, de l'autre les fonctions membres .read et .write

n°854783
nathan_g
Posté le 21-09-2004 à 13:10:26  profilanswer
 

Excuse moi, mais je ne te comprends pas. Je cherche juste à écrire plusieurs valeurs dans un fichier, c'est tout !
 
Quand à ma question, c'est juste de savoir si les commandes  :
 
ofs.write((int *) &numb,sizeof(int));  
 
et :
 
ofs << numb;  
 
sont équivalentes quand il s'agit d'écrire des valeurs dans un fichier binaire. Visiblement, pour moi ce n'est pas le cas. La première fait ce que j'attends mais la seconde me donne l'impression de procéder à une écriture ASCII. D'où viens ce problème ? Est ce que les sémantiques sont équivalentes comme le dit Taz pour des fichiers binaires ou ce n'est plus le cas dans une telle situation ?

n°854984
nathan_g
Posté le 21-09-2004 à 15:59:16  profilanswer
 

Juste un autre point :
 
Est ce dangereux d'utiliser les cast tels que je le fais. En effet, si je veux mettre un entier ou un double en binaire dans un fichier et que << ne semble pas marcher, je suis obligé de me rabattre vers la commande write. Or celle-ci, selon sa déclaration, ne devrait accepter que les pointeur du type char* en premier argument. En en utilisant un autre (ie. (int *) ), cette écriture semble pourtant fonctionner (en regardant ce qui se passe pour la lecture). Est ce dangereux ? Si << surchargé ne fonctionne pas, comment puis-je avec la commande write, faire une écriture en binaire d'un entier ou d'un double ?
 

n°855132
Taz
bisounours-codeur
Posté le 21-09-2004 à 18:01:50  profilanswer
 

si t'as arrêter de caster dans tous les sens et que tu écrivais les choses bien ... ça serait plus indolore

n°855143
nathan_g
Posté le 21-09-2004 à 18:11:56  profilanswer
 

Bon ...
1)
 
Je voudrais juste une réponse claire à ma question sur l'équivalence des deux écritures pour un fichier binaire.
 
2)
 
Qu'est ce que se serait pour toi, Taz, une écriture propre de :
 
ofs.write((int *) &numb,sizeof(int));
 
si l'on souhaite écrire une variable numb, de type int,  dans un fichier (binaire ou ASCII puisque cette commande write est valable pour les deux types de fichiers, enfin, je crois). Je reconnais que mon bouquin de C++ parle d'un modèle d'écriture en : write(const char* tampon, int max).

n°855214
blackgodde​ss
vive le troll !
Posté le 21-09-2004 à 20:17:36  profilanswer
 

ofs.write((int *) &numb,sizeof(int));  
si numb est un int, pourquoi tu le recast en int ?
puis doit y avoir un const perdu en plus
ofs.write(&numb, sizeof(int));
 
sinon (type*)&var c'est un cast C, en C++ pour obtenir la meme chose on ecrit dynamic_cast<type*>(&var) ou si on peut résoudre le transtypage a la compilation static_cast<type*>(&var)


---------------
-( BlackGoddess )-
mood
Publicité
Posté le 21-09-2004 à 20:17:36  profilanswer
 

n°855235
Taz
bisounours-codeur
Posté le 21-09-2004 à 20:46:48  profilanswer
 

mais &numb EST un int* !

n°855367
blackgodde​ss
vive le troll !
Posté le 22-09-2004 à 00:44:45  profilanswer
 

bin oui, c'est ce que j'ai écrit :o
ofs.write(&numb, sizeof(int));


---------------
-( BlackGoddess )-
n°855369
Taz
bisounours-codeur
Posté le 22-09-2004 à 00:52:17  profilanswer
 

moi j'aime bien le sizeof numb

n°855423
nathan_g
Posté le 22-09-2004 à 09:09:49  profilanswer
 

Bon ...
 
Aucune idée de la raison pour laquelle les deux écritures possibles ne donne pas le même résultat pour les fichiers binaires ?
 
Sinon, quel est l'écriture correcte de la commande write si l'on souhaite écrire un int dans un fichier. On a alors , effectivement, un int* en paramètre d'entrée et non un char*. Comme résoudre ce problème ?

n°855433
Lam's
Profil: bas.
Posté le 22-09-2004 à 09:32:57  profilanswer
 

nathan_g a écrit :

Aucune idée de la raison pour laquelle les deux écritures possibles ne donne pas le même résultat pour les fichiers binaires ?


 
Comme tu l'as bien compris, les flux c'est pour du texte (donc la représentation textuelle des entiers, caractères, etc.), et write c'est pour du binaire (donc, leur représentation machine), c'est tout.  
 
La façon C++, ça serait:  

Code :
  1. osf.write(static_cast<const char *>(&i), sizeof int);


 
 
Mais franchement, mon avis (religieux) personnel, c'est qu'un cast C classique ne fait pas de mal dans le contexte en cours (qui est de détyper un pointeur sur un type primitif pour le passer à une API). Si c'était une affectation de pointeurs sur des types non-basiques (struct ou class), ça serait effectivement à éviter. Les avis diffèrent, et franchement, ça devrait être le cadet de tes soucis...
 

n°855446
nathan_g
Posté le 22-09-2004 à 09:50:56  profilanswer
 

OK, merci de cette réponse claire.
Sinon, tu écris que les flux c'est pour du texte ce qui pourrais expliquer mon problème de ne pas pouvoir écrire de fichiers binaires avec ces flux. La, je suis étonné car dans mon bouquin de C++, les écriture de int dans des fichiers ASCII se font par des flux (ex : ofs << i; où i est une variable int). Leurs lectures se fait également par des flux (ex : ifs >> i;) et ça fonctionne.
Il est donc possible d'écrire des variables int dans des fichiers ASCII et de les relire. Ou alors, je n'ai pas très bien compris ce que tu entends par "texte". Tu voulais peut-être me dire qu'il s'agissait de fichiers ASCII et que les flux sont des méthodes d'écriture/lecture réservées aux fichiers ASCII ?
 
Sur le second point, je vais peut être adoptée quand même, par propreté l'écriture :
 
osf.write(static_cast<const char *>(&i), sizeof int);
 
Mais d'après ce que j'ai cru comprendre, il n'y aucun risque dans l'éxécution à écrire :
 
ofs.write((int *) &numb,sizeof(int));  
 
A part que mon compilateur affiche alors un warning pour cette ligne.

n°855447
nathan_g
Posté le 22-09-2004 à 09:51:43  profilanswer
 

( ifs >> i ; ) bien sur.

n°857267
nathan_g
Posté le 24-09-2004 à 17:58:03  profilanswer
 

UP !
 
Je reviens sur mon post car j'aimerais avoir confirmation des questions que je continue à me poser.
 
De plus, j'ai toujours ce problème d'écrire dans des fichiers. La commande :
 
ofs << value;
 
m'écrit des variables de manière claire dans des fichiers, donc crée un fichier de type ASCII.
 
La commande  
 
ofs.write((int* ) &value,sizeof(int));
 
m'écrit des variables apparemment en binaire (car les fichiers sont illisibles avec more).
 
En plus, le fonctionnement de ces commandes semble indépendant du format d'ouverture du fichier (ie. que l'instruction ios::binary soit ou non préciser à l'ouverture du fichier dans la commande ofs.open("Mon fichier",ios::out|ios::binary).
 
D'où vient ce comportement ?

n°857686
HelloWorld
Salut tout le monde!
Posté le 25-09-2004 à 18:56:02  profilanswer
 

Ben c'est fait comme ça, c'est le comportement voulu. L'opérateur << manipule des flux text, pas binaire. Faire un truc genre :
fichier << ios_base::binary << 11;
devrait plutot afficher "1011" (11 en binaire, mais toujours sous forme texte). C'est la seule manière d'avoir une sortie portable, i.e. pas avoir de problemes de little/big endian.
Pour écrire en binaire on utilise write. Ca écrit des octets. Un cast bête est pratique mais sans garantie de portabilite. L'ideal est de choisir une représentation binaire et d'avoir des routines qui en fonction du système transforme (ou non) les données en mémoire dans ce format binaire décidé. Idem pour la lecture.
Je sais qu'il y a boost::serialization pour ça, mais j'ai pas testé.
Pour une utilisation "interne" restreinte, un truc du genre fait l'affaire :

Code :
  1. template<typename T>
  2. void write( std::ofstream & Stream, T Value )
  3. {
  4.     Stream.write( reinterpret_cast<char*>( &Value ), sizeof T );
  5. }


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°857690
Taz
bisounours-codeur
Posté le 25-09-2004 à 19:02:54  profilanswer
 

mais pourquoi typer en ofstream bordel :o
 
et une chtite référence siouplé pour Value

n°858504
HelloWorld
Salut tout le monde!
Posté le 27-09-2004 à 01:33:51  profilanswer
 

Taz a écrit :

mais pourquoi typer en ofstream bordel :o


Pas compris.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°858543
Taz
bisounours-codeur
Posté le 27-09-2004 à 20:18:57  profilanswer
 

pourquoi avoir fait une fonction pour ofstream uniquement ?

n°858792
nathan_g
Posté le 28-09-2004 à 08:57:11  profilanswer
 

Bon, je vais essayer la proposition de HelloWorld.
Mais, je reste sur ma fin. Je n'ai toujours pas compris l'intérêt d'écrire ios::binary au début du programme vu que le format d'écriture (respectivement lecture) est guidé uniquement par le choix de << (respectivement >> ) ou de write (respectivement read). Dans le premier, c'est de l'ASCII, dans le second du binaire. Etonnant non ?

n°858803
HelloWorld
Salut tout le monde!
Posté le 28-09-2004 à 09:17:56  profilanswer
 

Oui. ios_base::binary influe sur les retours chariots. Sous Windows y'a 2 carcatères pour revenir à la ligne, sans binary c'est comme si y'en avait qu'un.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°858805
xterminhat​e
Si vis pacem, para bellum.
Posté le 28-09-2004 à 09:19:52  profilanswer
 

D'expérience, lire ou écrire avec ostream::write et istream::read sans préciser que le flux est de type binaire entraine des erreurs (ton fichier comporterait des anomamlies!).


---------------
Cordialement, Xterm-in'Hate...
n°858824
nathan_g
Posté le 28-09-2004 à 09:37:58  profilanswer
 

OK, Merci beaucoup !
 
Enfin, la réponse que j'attendais. Je vais revoir mon programme en reconsidérant tout ça et en utilisant le petit programme de HelloWorld.
 
Pour information, ce que je dois faire est en fait la relecture, par mon programme C++, d'un fichier binaire écrit en fortran 77. On découvre des caractères surprise !
 
Par tatonnement, j'ai d'ailleurs découvert que l'écriture d'un ensemble de valeurs, en fortran, se faisait en rajoutant des données supplémentaires indiquant la taille des variables.
 

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Ecriture/Lecture de fichier binaire (ios::binary) avec << et >>

 

Sujets relatifs
problème pour changer de place un fichier log sous SQL server 2000 ...taille d'un fichier transmis par FTP ?
[PHP - Debutant] Comment telecharger un fichier?debutant , comment executer un fichier php
flux vers fichier ET vers console en même tempsASP.NET C# formulaire mode lecture seule
Interface de partage de fichierzone de sélection d'un dossier et non d'un fichier
[PHP] Effacer un fichier ?PB avec delphi 6 : delphi se ferme a l'ouverture d'un fichier
Plus de sujets relatifs à : Ecriture/Lecture de fichier binaire (ios::binary) avec << et >>


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR