OVH Cloud OVH Cloud

Entrees sorties binaires

14 réponses
Avatar
Gregoire Mercier
Salut,

Je suis entrain de convertir mes vieilles sources de g++296 pour un g++=20
un peu plus r=E9cent et, horreur, mes entr=E9es sorties binaires ne march=
ent=20
plus !

Exit le fp.read( (char *) ptr, sizeof( double ) * n ) ????

Quelle est l'=E9quivalent =E9l=E9gant sur une version de gcc 3.4.3 ? Ne m=
e=20
dites pas qu'il faille revenir au fread() du C ?? Dans ce cas, comment=20
passe-t-on d'un ifstream =E0 un FILE * sans avoir =E0 tout r=E9=E9crire ?=
??

Merci,
Greg

10 réponses

1 2
Avatar
kanze
Gregoire Mercier wrote:

Je suis entrain de convertir mes vieilles sources de g++296
pour un g++ un peu plus récent et, horreur, mes entrées
sorties binaires ne marchent plus !

Exit le fp.read( (char *) ptr, sizeof( double ) * n ) ????


Ça veut dire quoi, exactement, « ne marchent plus » ? Ça marche
chez moi.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Gregoire Mercier
Et bien, cela "marchait" (ie faisait ce que je voulais et esperais !) en
g++296 pour décoder des images (effectivement codées en double par
pixel, et même en complexe mais ca, c'est une autre histoire).

Avec cette version 3 de gcc, je n'ai pas vraiment identifié le problè me
mais cela me donne n'importe quoi comme valeur numérique (mais cela
compile et s'execute). J'ai l'impression que le read permet de lire
n*sizeof(double) octets mais les considère toujours comme de l'ASCII et
non en binaire "brut de décoffrage"...

Greg

wrote:
Gregoire Mercier wrote:


Je suis entrain de convertir mes vieilles sources de g++296
pour un g++ un peu plus récent et, horreur, mes entrées
sorties binaires ne marchent plus !



Exit le fp.read( (char *) ptr, sizeof( double ) * n ) ????



Ça veut dire quoi, exactement, « ne marchent plus » ? Ça marche
chez moi.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34




Avatar
Falk Tannhäuser
Gregoire Mercier wrote:

Avec cette version 3 de gcc, je n'ai pas vraiment identifié le problè me
mais cela me donne n'importe quoi comme valeur numérique (mais cela
compile et s'execute). J'ai l'impression que le read permet de lire
n*sizeof(double) octets mais les considère toujours comme de l'ASCII et
non en binaire "brut de décoffrage"...


As-tu ouvert ton fichier en spécifiant le flag std::ios::binary
(lors de l'écriture ainsi que lors de la relecture) ? Est-ce que
tu relis ton fichier binaire sur le même type de machine que celui
sur lequel il a été écrit ?

Falk

Avatar
Gregoire Mercier
Yep,

J'avais ajouté std::ios_base::binary.
A priori, c'est effectivement des données que j'ai créées moi-mêm e mais
je voudrais que ce ne soit pas un critère !
Pour info, le décodage fonctionne correctement avec des images en pgm
(unsigned char par pixel)....

Greg


Falk Tannhäuser wrote:
Gregoire Mercier wrote:

Avec cette version 3 de gcc, je n'ai pas vraiment identifié le
problème mais cela me donne n'importe quoi comme valeur numérique
(mais cela compile et s'execute). J'ai l'impression que le read permet
de lire n*sizeof(double) octets mais les considère toujours comme de
l'ASCII et non en binaire "brut de décoffrage"...



As-tu ouvert ton fichier en spécifiant le flag std::ios::binary (lors de
l'écriture ainsi que lors de la relecture) ? Est-ce que
tu relis ton fichier binaire sur le même type de machine que celui
sur lequel il a été écrit ?

Fal
k



Avatar
Cyrille
Yep,

J'avais ajouté std::ios_base::binary.
A priori, c'est effectivement des données que j'ai créées moi-même mais
je voudrais que ce ne soit pas un critère !
Pour info, le décodage fonctionne correctement avec des images en pgm
(unsigned char par pixel)....


Est-ce que tu pourrais nous pondre un code de quelques lignes qui
reproduit ton problème?

--
"I have nothing to declare except war on Austria." ~ Oscar Wilde, 1936

Avatar
kanze
Gregoire Mercier wrote:
Et bien, cela "marchait" (ie faisait ce que je voulais et
esperais !) en g++296 pour décoder des images (effectivement
codées en double par pixel, et même en complexe mais ca, c'est
une autre histoire).

Avec cette version 3 de gcc, je n'ai pas vraiment identifié le
problème mais cela me donne n'importe quoi comme valeur
numérique (mais cela compile et s'execute). J'ai l'impression
que le read permet de lire n*sizeof(double) octets mais les
considère toujours comme de l'ASCII et non en binaire "brut de
décoffrage"...


On entre alors dans une zone un peu complexe. En théorie, au
moins ; dans la pratique, si tu ouvres les fichiers toujours en
mode binaire (et en écriture, et à la lecture), tu dois
récupérer en lecture toujours les octets que tu y a écrit, sans
changement. (Je suppose ici que tu n'est pas sur une plateforme
exotique, avec des char de 9 bits ou quelque chose de
semblable.) Ensuite, évidemment, il y a la question de
l'interprétation de ces octets, qui dépend surtout du hardware
sur lequel tourne le programme -- les données binaires brutes
écrites par un Sparc ne sont pas lisibles sur un PC, par
exemple. (Surtout du hardware, mais pas exclusivement -- ça peut
aussi dépendre des versions ou des options du compilateur. Mais
ce n'est pas le cas ici.)

Si tu tournes sur la même machine en écriture et en lecture, et
que tu as ouvert les fichiers toujours en mode binaire, ça doit
marcher (avec g++, en tout cas). Si les machines sont
différentes, il n'y a pas de raison que ça marche. C'est pour ça
qu'on n'écrit pour ainsi dire jamais des données en image brute
de la mémoire. On formatte toujours. (Il existe des formats
binaires, du très simple XDR au plus complexe BER -- le format
flottant en BER est particulièrement compliqué.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Gregoire Mercier
Merci pour ces explications. En fait le problème est à la fois plus
simple et plus complexe.

Plus simple parce que je peux aussi avoir à traiter des données
formattées en FloatIEEE et là il n'y a rien d'exotique.

C'est un peu plus complexe puisque mes sources en C++ fonctionnent
depuis 5 à 10 ans (j'ai maintenant plus de 10Mo de sources!) et peuvent
lire des données avec à peu près tous les types normaux, quelque so it le
sens du MSB ou LSB... Par contre un même sources (basé sur le fameux
fp.read(...);) va très bien fonctionner lorsqu'il est compilé avec
g++296 mais va "decoder" n'importe quoi lorsque je le compile avec les
version courantes de g++ sur les même données et sur les machines lin ux.

Je crois que le language a changé le sens des entrées / sorties binai res
et j'ai cru lire quelque part dans une doc de STL que les
entrées/sorties étaient à présent orientée "texte" plutôt que binaire...
Mais dans ce cas, faut-il revenir au instruction C pour faire ces
entrées sorties binaires ??

Merci de votre aide!
Greg


wrote:
Gregoire Mercier wrote:

Et bien, cela "marchait" (ie faisait ce que je voulais et
esperais !) en g++296 pour décoder des images (effectivement
codées en double par pixel, et même en complexe mais ca, c'est
une autre histoire).



Avec cette version 3 de gcc, je n'ai pas vraiment identifié le
problème mais cela me donne n'importe quoi comme valeur
numérique (mais cela compile et s'execute). J'ai l'impression
que le read permet de lire n*sizeof(double) octets mais les
considère toujours comme de l'ASCII et non en binaire "brut de
décoffrage"...



On entre alors dans une zone un peu complexe. En théorie, au
moins ; dans la pratique, si tu ouvres les fichiers toujours en
mode binaire (et en écriture, et à la lecture), tu dois
récupérer en lecture toujours les octets que tu y a écrit, sans
changement. (Je suppose ici que tu n'est pas sur une plateforme
exotique, avec des char de 9 bits ou quelque chose de
semblable.) Ensuite, évidemment, il y a la question de
l'interprétation de ces octets, qui dépend surtout du hardware
sur lequel tourne le programme -- les données binaires brutes
écrites par un Sparc ne sont pas lisibles sur un PC, par
exemple. (Surtout du hardware, mais pas exclusivement -- ça peut
aussi dépendre des versions ou des options du compilateur. Mais
ce n'est pas le cas ici.)

Si tu tournes sur la même machine en écriture et en lecture, et
que tu as ouvert les fichiers toujours en mode binaire, ça doit
marcher (avec g++, en tout cas). Si les machines sont
différentes, il n'y a pas de raison que ça marche. C'est pour ça
qu'on n'écrit pour ainsi dire jamais des données en image brute
de la mémoire. On formatte toujours. (Il existe des formats
binaires, du très simple XDR au plus complexe BER -- le format
flottant en BER est particulièrement compliqué.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34




Avatar
Jean-Marc Bourguet
Gregoire Mercier writes:

Plus simple parce que je peux aussi avoir à traiter des données
formattées en FloatIEEE et là il n'y a rien d'exotique.


La norme ne garantit aucune representation physique. Et il me semble
qu'elles varient suivant les ordinateurs (et plus que big/little
endian).

C'est un peu plus complexe puisque mes sources en C++ fonctionnent
depuis 5 à 10 ans (j'ai maintenant plus de 10Mo de sources!) et
peuvent lire des données avec à peu près tous les types normaux,
quelque soit le sens du MSB ou LSB... Par contre un même sources
(basé sur le fameux fp.read(...);) va très bien fonctionner
lorsqu'il est compilé avec g++296 mais va "decoder" n'importe quoi
lorsque je le compile avec les version courantes de g++ sur les même
données et sur les machines linux.

Je crois que le language a changé le sens des entrées / sorties
binaires et j'ai cru lire quelque part dans une doc de STL que les
entrées/sorties étaient à présent orientée "texte" plutôt que
binaire... Mais dans ce cas, faut-il revenir au instruction C pour
faire ces entrées sorties binaires ??


Non.

La seule difference possible que je vois est dans le traitement de la
localisation. Les linux recents ayant une certaine preference pour
l'UTF-8, ca peut expliquer. Est-ce que
is.imbue(std::locale::classic())
resoud ton probleme?

Sinon, il faudra essayer de reproduire avec un programme d'une taille
acceptable si tu veux qu'on t'aide.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
kanze
Gregoire Mercier wrote:
Merci pour ces explications. En fait le problème est à la fois
plus simple et plus complexe.

Plus simple parce que je peux aussi avoir à traiter des
données formattées en FloatIEEE et là il n'y a rien
d'exotique.


IEEE ne spécifie pas la représentation de son format en mémoire.
En fait, sur ma machine Linux, chez moi, et les Sun au travail,
la représentation n'est pas pareil.

Et évidemment, il y a encore des machines dont le flottant n'est
pas IEEE. (Les IBM 390, par exemple, ou les Unisys 2200.)

C'est un peu plus complexe puisque mes sources en C++
fonctionnent depuis 5 à 10 ans (j'ai maintenant plus de 10Mo
de sources!) et peuvent lire des données avec à peu près tous
les types normaux, quelque soit le sens du MSB ou LSB... Par
contre un même sources (basé sur le fameux fp.read(...);) va
très bien fonctionner lorsqu'il est compilé avec g++296 mais
va "decoder" n'importe quoi lorsque je le compile avec les
version courantes de g++ sur les même données et sur les
machines linux.

Je crois que le language a changé le sens des entrées /
sorties binaires et j'ai cru lire quelque part dans une doc de
STL que les entrées/sorties étaient à présent orientée "texte"
plutôt que binaire... Mais dans ce cas, faut-il revenir au
instruction C pour faire ces entrées sorties binaires ??


Le langage a bien changé un peu : selon la norme, même les
entrées/sorties « binaires » sont transcodés ; en plus de
spécifier ios::binary, il faut imuer un locale un-à-un ; la plus
sûr, c'est de faire flux.imbue( std::locale::classic() ) avant
les premières entrées/sorties.

Mais d'un certain côté, c'est une modification « nineur ». Parce
que depuis tout le temps, les flux sont orientés textes ; le
support pour le binaire a toujours été assez limité, et
seulement dans la mesure que ça ne genait pas le texte. La même
chose vaut pour les flux de C, d'ailleurs.

En C++, en général, quand on veut un flux binaire, on écrit ses
propres flux, à base de ios et des streambuf. (Dans le temps,
Diemar Kühl en avait une implémentation sur la toile.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Gregoire Mercier
Pour finir, j'ai eu plus ou moins confirmation sur comp.lang.c++ que les
flux d'entrées sorties étaient essentiellement orientés vers le
formattage du texte. Le flux.imbue( std::locale::classic() ) resout
effectivement les choses mais jusqu'à quelle version ???

Pour ma part (et pour une part importante de RegExp en perl ;-) je suis
repassé au bon view fwrite et fread...

Merci à tous
Greg

wrote:
Gregoire Mercier wrote:

Merci pour ces explications. En fait le problème est à la fois
plus simple et plus complexe.



Plus simple parce que je peux aussi avoir à traiter des
données formattées en FloatIEEE et là il n'y a rien
d'exotique.



IEEE ne spécifie pas la représentation de son format en mémoire.
En fait, sur ma machine Linux, chez moi, et les Sun au travail,
la représentation n'est pas pareil.

Et évidemment, il y a encore des machines dont le flottant n'est
pas IEEE. (Les IBM 390, par exemple, ou les Unisys 2200.)


C'est un peu plus complexe puisque mes sources en C++
fonctionnent depuis 5 à 10 ans (j'ai maintenant plus de 10Mo
de sources!) et peuvent lire des données avec à peu près tous
les types normaux, quelque soit le sens du MSB ou LSB... Par
contre un même sources (basé sur le fameux fp.read(...);) va
très bien fonctionner lorsqu'il est compilé avec g++296 mais
va "decoder" n'importe quoi lorsque je le compile avec les
version courantes de g++ sur les même données et sur les
machines linux.



Je crois que le language a changé le sens des entrées /
sorties binaires et j'ai cru lire quelque part dans une doc de
STL que les entrées/sorties étaient à présent orientée "texte "
plutôt que binaire... Mais dans ce cas, faut-il revenir au
instruction C pour faire ces entrées sorties binaires ??



Le langage a bien changé un peu : selon la norme, même les
entrées/sorties « binaires » sont transcodés ; en plus de
spécifier ios::binary, il faut imuer un locale un-à-un ; la plus
sûr, c'est de faire flux.imbue( std::locale::classic() ) avant
les premières entrées/sorties.

Mais d'un certain côté, c'est une modification « nineur ». Parc e
que depuis tout le temps, les flux sont orientés textes ; le
support pour le binaire a toujours été assez limité, et
seulement dans la mesure que ça ne genait pas le texte. La même
chose vaut pour les flux de C, d'ailleurs.

En C++, en général, quand on veut un flux binaire, on écrit ses
propres flux, à base de ios et des streambuf. (Dans le temps,
Diemar Kühl en avait une implémentation sur la toile.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34




1 2