OVH Cloud OVH Cloud

ofstream et fonction write template

78 réponses
Avatar
Aurélien REGAT-BARREL
Bonjour à tous,
Pour mes besoins j'ai défini une fonction write ainsi :

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

void main()
{
std::ofstream OutFileStream;
OutFileStream.open( "test" );
int c = 10;
write( OutFileStream, c );
}

Je m'étonne qu'elle n'existe pas déjà dans la STL, ou même carrement en tant
que fonction membre de ofstream. Je pense plutôt que j'ai mal cherché.
Y'a-t-il un équivalent et si non pourquoi ?
Merci.

--
Aurélien REGAT-BARREL

10 réponses

1 2 3 4 5
Avatar
Loïc Joly
Aurélien REGAT-BARREL wrote:
[...]


Aujourd'hui, ne ne voit que les points suivants sur lesquels le binaire
peut s'avérer intéressant :


[..]

Comme l'a dit Fabien, quand les fichiers comment à dépasser le mega, le
binaire devient très intéressant. Au boulot on manipule "à la main" des
données ASCII (pratique pour les tests, etc...) mais une fois que c'est ok,
on passe le tout à la moulinette -> binaire. Ca réduit la taille par ~10,


Ca peut dépendre des données. Si 90% des tes doubles valent 0, tu y
gagnes peut-être un format texte, d'autant plus si tu compresses. Mais
je suis d'accord avec toi dans le cas général.

et
le temps de chargement par XXX (convertir des millions de nombres flottants,
c'est long !)


Intuitivement, j'aurais plutôt tendance à dire que la majeure partie du
temps de traitement quand c'est écrit en textuel, c'est probablement dû
au fait que ça prend plus de place.

Dans un cas comme ça compresser fait gagner d'un côté (taille) mais perdre
de l'autre (temps : en plus de la conversion très longue, y'a la
compression/decompression).


Je n'en suis qu'à moitié sur, et comme dans tous ces cas, il n'y a que
la mesure qui compte. Ce dont je suis sur, c'est qu'au temps des
disquette, compresser sur disque dur mettre sur disquette pour
transporter le fichier et le décompresser à l'arrivée faisait gagner du
temps, malgré les interventions manuelles. Les disques dur ou couches
réseau sont certes plus rapides, mais par rapport à la mémoire, qu'en
est-il ?


--
Loïc


Avatar
Fabien LE LEZ
On Thu, 19 Aug 2004 20:31:29 +0200, Loïc Joly
:

Ca peut dépendre des données. Si 90% des tes doubles valent 0,


Si une telle situation est fréquente, le format est mal choisi.

Dans un cas comme ça compresser fait gagner d'un côté (taille) mais perdre
de l'autre (temps : en plus de la conversion très longue, y'a la
compression/decompression).


Je n'en suis qu'à moitié sur, et comme dans tous ces cas, il n'y a que
la mesure qui compte.


Sur mon petit PC (Athlon XP 2000+), la compression en ZIP (un des
formats les plus rapides) d'un fichier texte de 10 Mo demande 4
secondes, soit environ 2 Mo/s.
En se basant sur ce petit test, et aussi un peu sur mon expérience, je
dirais que compresser pour enregistrer sur un disque dur local (20
Mo/s minimum) ralentit sérieusement l'enregistrement, mais si ça doit
passer par un réseau, la question se pose (sauf peut-être sur un 100
Mbps très peu chargé) -- et il faut faire des tests plus précis.


--
;-)


Avatar
Loïc Joly
Fabien LE LEZ wrote:

On Thu, 19 Aug 2004 20:31:29 +0200, Loïc Joly
:


Ca peut dépendre des données. Si 90% des tes doubles valent 0,



Si une telle situation est fréquente, le format est mal choisi.


Ca dépend. Par exemple, si on transmet les données d'un capteur le plus
souvent au repos, mais qu'on est obligé d'interroger par polling ?

Dans un cas comme ça compresser fait gagner d'un côté (taille) mais perdre
de l'autre (temps : en plus de la conversion très longue, y'a la
compression/decompression).


Je n'en suis qu'à moitié sur, et comme dans tous ces cas, il n'y a que
la mesure qui compte.



Sur mon petit PC (Athlon XP 2000+), la compression en ZIP (un des
formats les plus rapides) d'un fichier texte de 10 Mo demande 4
secondes, soit environ 2 Mo/s.


Mais là, tiens tu aussi compte de la lecture du fichier initial et de
l'écriture du résultat, ou uniquement du traitement en mémoire à
proprement parler ?


En se basant sur ce petit test, et aussi un peu sur mon expérience, je
dirais que compresser pour enregistrer sur un disque dur local (20
Mo/s minimum) ralentit sérieusement l'enregistrement, mais si ça doit
passer par un réseau, la question se pose (sauf peut-être sur un 100
Mbps très peu chargé) -- et il faut faire des tests plus précis.


--
Loïc



Avatar
kanze
"Aurélien REGAT-BARREL" wrote in
message news:<41249c72$0$8970$...

Comme on te l'as dit, non seulement reinterpret_cast n'est pas
nécessaire, mais en plus, c'est une erreur de l'utiliser dans ce
contexte. Il faut définir mauellement le format binaire que l'on
soihaite avoir, puis convertir nos données en tableau de char selon
cette définition.


C'est une tâche assez laborieuse, surtout quand on ne vise pas la
portabilité et qu'on est assuré que le format du fichier et le format
interne sont les mêmes, ce qui est mon cas.


Portabilité, c'est rélative. Ici, il s'agit de la portabilité des
données, et la possibilité de les rélire quand on fait une mise à jour
du compilateur. (Ça peut te semblait assez gros, mais j'ai déjà eu un
cas où l'ordre des octets dans un long n'était pas le même entre deux
versions du compilateur. Je suis donc bien sensibilisé au problème.)

En général, s'il s'agit d'un fichier temporaire, où tu stockes des
données que tu rélis plus tard dans la même exécution du programme, il
n'y a pas de problème -- un dump mémoire peut servir. Dans tous les
autres cas, y compris quand tu rélis les données à la prochaine
exécution du même programme seulement, tu le dois aux gens qui te
suivent d'au moins documenter le format quelque part, pour qu'ils aient
une chance de pouvoir récupérer les données, le cas échéant.

En passant, j'ajouterai que je parle dans un contexte des logiciels
commerciaux ou industriels. Dans le cas d'un jeu, par exemple, ça me
semble moins évident. Quand je fais une mise à jour de nethack, par
exemple, je perds parfois des sauvegardes des jeux en cours, et même des
fichiers de « bones », qui permettent de rétomber sur des niveaux où on
s'est fait tuer avant. Et je n'en ai rien à rédire. Alors, c'est un peu
à toi de voir. Mais sois méfiant -- si les données ont la moindre
importance, comme j'ai dit, le minimum, c'est de documenter exactement
le format.

Et enfin : une fois le format précisement documenté, écrire les
fonctions pour l'écrire et le lire proprement est un jeu d'enfant.

Dans cette situation, est-ce acceptable d'utiliser reinterpret_cast ?


Du moment qu'on est dans une contexte où la portabilité ne joue pas,
tout est permis. En fait, pour ce genre de chose, j'aurais une tendance
à utiliser les fonctions du système directement, sans passer par les
iostream. (Les fonctions open, write et close chez moi, par exemple.)

Cette fonction template avait juste pour but d'alléger l'écriture.
fwrite accepte un void *, pourquoi ostream::write ne fait pas de
même ?


Parce qu'elle accepte un char*, et que autant je sais ce qu'écrire
un char veut dire, autant j'ignore ce que peut vouloir dire écrire
un void.


Ben fwrite le sait bien elle...


On n'est pas obligé à dupliquer les erreurs de la bibliothèque C. La
bibliothèque C fait une passe sur le typage à plusieurs endroits.

Mais bon je saisis un peu mieux le truc, ce que j'ai enfin compris
c'est qu'il faut écrire sa routine qui sérialise ses données en un
tableau de char. Ce que je trouve "aberrant" (vous aurez compris que
ce mot était volontairement trop fort et avait pour but de susciter
des réactions ;-) c'est qu'il n'y ait rien dans la SL qui guide le
programmeur dans ce sens, genre une fonction write templatée qui
accepte/appelle un serialiser, ou des fonctions d'aide à la
sérialisation, ou autre chose.


La norme ne s'adresse pas à la question de la sérialisation. On peut en
discuter si c'est une bonne chose ou non. J'avoue que je suis sceptique.
Mais c'est sans doute parce que je me suis servi de Java, où la
sérialisation fait partie de la spécification, et j'ai vu les problèmes
que ça posait là.

Je trouve que c'est pas évident du tout qu'il faille procéder ainsi,
et j'ai peur de ne pas être le seul. Existe-t-il quelque chose
ailleurs, dans boost par exemple, qui soit indiqué dans ce cas ?

James a parlé de oberstream et d' oxdrstream, mais je n'ai rien trouvé
:-(


C'était à titre d'exemple de ce qu'on pourrait faire. Bien que je crois
qu'à un époque, Dietmar Kühl avait une implémentation d'un [io]xdrstream
disponible sur le reseau. Il en a existé d'autres -- voir par exemple
http://www.medusa.uni-bremen.de/intern/orpc/node4.html (mais je ne sais
pas si ce projet est actuel, ni si le logiciel qu'il décrit est
librement disponible).



Avatar
kanze
"M. B." wrote in message
news:<cg2flk$lv3$...
"Loïc Joly" a écrit dans le message de
news: cg2esa$q5a$
Aurélien REGAT-BARREL wrote:

Dans l'autre sens, je vois les points suivants :
- Un format plus simple à debugger, analyser...
- Du code plus simple à écrire

Y a-t-il d'autres arguments dans un sens ou un autre ?


Pour rester du cote textuel, les avantages d'XML sont
innombrables.


Surtout pour des vendeurs de disques, de mémoire et de bande passante.

--
James Kanze GABI Software http://www.gabi-soft.fr
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
kanze
drkm wrote in message
news:...
Loïc Joly writes:

- Il y a des types (flottants) pour lesquels une représentation
textuelle classique fait perdre de l'information.


Je ne sais pas ce que tu entends par « classique », mais il est
toujours possible de spécifier une représentation textuelle inspirée
de la représentation binaire utilisée par ton implémentation.

Mais il me semble que si tu analyses bien tes besoins, il y a moyen
de spécifier un format où tu représentes la mantisse, l'exposant, etc.
sous forme d'entiers textuels, de manière à disposer de la précision
dont tu as besoin. Le fait que certaines implémentations pourrait ne
pas garantir une telle précision est ici hors propos.

Il me semble, du moins.


Si ton format interne est IEEE, tu es garanti avec une précision de 17
(ou peut-être 18 -- il faudrait que je vérifie) qu'une conversion
double->ascii->doube ne perd aucune information (en supposant une
implémentation « correcte » de la bibliothèque, évidemment).

--
James Kanze GABI Software http://www.gabi-soft.fr
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
M. B.
a écrit dans le message de news:

"M. B." wrote in message
news:<cg2flk$lv3$...
"Loïc Joly" a écrit dans le message de
news: cg2esa$q5a$
Aurélien REGAT-BARREL wrote:

Dans l'autre sens, je vois les points suivants :
- Un format plus simple à debugger, analyser...
- Du code plus simple à écrire

Y a-t-il d'autres arguments dans un sens ou un autre ?


Pour rester du cote textuel, les avantages d'XML sont
innombrables.


Surtout pour des vendeurs de disques, de mémoire et de bande passante.



C'est grotesque ...

MB



Avatar
Loïc Joly
M. B. wrote:
"Loïc Joly" a écrit dans le message de news:
cg2esa$q5a$

Aurélien REGAT-BARREL wrote:

Dans l'autre sens, je vois les points suivants :
- Un format plus simple à debugger, analyser...
- Du code plus simple à écrire

Y a-t-il d'autres arguments dans un sens ou un autre ?



Pour rester du cote textuel, les avantages d'XML sont
innombrables.


Personellement, j'ai un peu de mal avec XML :
- C'est un format qui hésite à être lisible par un être humain ou
lisible par une machine. Il a trop de symboles techniques pour qu'un
humain normal (=non programmeur) s'y retrouve, même avec les meilleurs
outils "génériques" derrière, et beaucoup trop de redondance pour un
langage lisible par une machine.

- Les schèmas sont une idée intéressante, mais ils introduisent une
dépandance supplémentaire. Maintenant, quand on décide d'ajouter un
champ à un objet, on doit modifier non seulement le code, le fichier,
mais aussi le xsd. En fait, il me manque un lien plus étroit entre code
et xsd. Il me semble que .NET propose ça, mais je n'ai jamais essayé.

- Il leur manque des fonctionnalités pour être des formats vraiment
intéressant directement pour stocker des objets. Par exemple une notion
de référence. Du coup, chacun bricole sa sauce, et ça ne sert plus à
rien d'avoir du XML, si chaque champ doit lui même être parsé.

- Enfin, mais ce n'est pas la faute du format, il y a eu tellement de
hype autour de celui-ci, que certains se sont mis à faire du XML pour le
XML, là ou un simple fichier texte lisible aurait été plus adapté.

En bref, et après avoir essayé, j'ai vu plein de problèmes par rapport à
un format de fichier adapté au domaine d'utilisation, mais je n'ai pas
vraiment vu les avantages. Peut-être que c'est simplement que je
travaille dans un domaine où les avantages ne sont pas utilisés ?

--
Loïc


Avatar
Loïc Joly
wrote:


Si ton format interne est IEEE, tu es garanti avec une précision de 17
(ou peut-être 18 -- il faudrait que je vérifie) qu'une conversion
double->ascii->doube ne perd aucune information (en supposant une
implémentation « correcte » de la bibliothèque, évidemment).


Si tu veux un format texte lisible (c'est à dire que affiche les double
de façon semblable à cette d'un std::cout), alors je ne vois pas trop
comment c'est possible, puisqu'une fraction peut avoir une
représentation non cyclique en base 10 et cyclique en base 2 et
réciproquement. As-tu une référence ?

--
Loïc

Avatar
Falk Tannhäuser
drkm wrote:

Loïc Joly writes:

- Il y a des types (flottants) pour lesquels une représentation
textuelle classique fait perdre de l'information.


Je ne sais pas ce que tu entends par « classique », mais il est
toujours possible de spécifier une représentation textuelle inspirée
de la représentation binaire utilisée par ton implémentation.

Mais il me semble que si tu analyses bien tes besoins, il y a moyen
de spécifier un format où tu représentes la mantisse, l'exposant,
etc. sous forme d'entiers textuels, de manière à disposer de la
précision dont tu as besoin. Le fait que certaines implémentations
pourrait ne pas garantir une telle précision est ici hors propos.


En C99 on a bien ajouté la représentation hexadécimale pour
les flottants (par exemple,
printf("%a %An", 6.55957, 0.00390625);
affiche "0x1.a3cffeb074a77p+2 0X1P-8".) Avec un peu de patience,
on aura peut-être quelque chose d'analogique dans les 'std::[io]stream'
à la prochaine révision de la Norme ...

Falk


1 2 3 4 5