Pourquoi 'ios::app'? Je n'ajoute pas des octets, mais je les remplace.
Merci.
pjb
Guillaume GOURDIN writes:
ofstream fout(path,ios::app);
Pourquoi 'ios::app'? Je n'ajoute pas des octets, mais je les remplace.
Pour se positionner dès l'ouverture en fin de fichier, en supposant qu'un certain nombre est assez petit.. Mais un ios::out irait aussi bien, je suppose.
-- __Pascal Bourguignon__
Guillaume GOURDIN <trash@hotmail.com> writes:
ofstream fout(path,ios::app);
Pourquoi 'ios::app'? Je n'ajoute pas des octets, mais je les remplace.
Pour se positionner dès l'ouverture en fin de fichier, en supposant
qu'un certain nombre est assez petit.. Mais un ios::out irait aussi
bien, je suppose.
Pourquoi 'ios::app'? Je n'ajoute pas des octets, mais je les remplace.
Pour se positionner dès l'ouverture en fin de fichier, en supposant qu'un certain nombre est assez petit.. Mais un ios::out irait aussi bien, je suppose.
-- __Pascal Bourguignon__
James Kanze
On Apr 7, 2:08 pm, Guillaume GOURDIN wrote:
j'ai besoin de remplacer un certain nombre d'octets à la fin d'un fichier. Comment procéderiez-vous? Faut-il utiliser un ofstream? Un ifstream?
La plupart du temps, dans de tels cas, j'utilise carrément l'interface Posix, avec des ostringstream pour formatter. Mais je n'ai pas besoin de portabilité (du moment que le code marche et sous Solaris et sous Linux), et j'ai besoins des écritures synchronisées. On peut bien le faire avec un fstream, en prenant des précautions nécessaires.
Plusieurs points importants :
-- L'ouverture en écriture seulement vide toujours le fichier, s'il existe déjà. Il faut absolument ouvrir en bidirectionnel, si tu veux y écrire, mais tu ne veux pas détruire tout le contenu précédant.
-- Si tu veux utiliser seek pour aller à un endroit arbitraire, il faut ouvrir en mode binaire ; sinon, tu n'as droit à seeker qu'au deux bouts ou à un endroit où tu as fait un tell.
-- Enfin, tu ne peux changer la taille du fichier qu'en ajoutant des octets à la fin. Si tu veux remplacer un enrégistrement dans le fichier, il faut que la taille du remplacement soit identique à la taille de ce que tu remplaces.
Donc, en supposant que tu saches déjà exactement où tu veux écrire, le code devient quelque chose comme :
std::ofstream dest( name, std::ios::in | std::ios::out | std::ios::binary ) ; dest.seekp( position, std::ios::beg ) ; // Sorties vers dest, en prenant bien soin du nombre // des octets générés.
Note que ce dernier point argue fort en faveur de l'utilisation d'un std::ostringstream pour le formattage, afin de pouvoir contrôle très exactement le nombre d'octets écrits (avec par exemple dest.write, plutôt que des opérateurs <<).
-- James Kanze (GABI Software) email: 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
On Apr 7, 2:08 pm, Guillaume GOURDIN <tr...@hotmail.com> wrote:
j'ai besoin de remplacer un certain nombre d'octets à la fin
d'un fichier. Comment procéderiez-vous? Faut-il utiliser un
ofstream? Un ifstream?
La plupart du temps, dans de tels cas, j'utilise carrément
l'interface Posix, avec des ostringstream pour formatter. Mais
je n'ai pas besoin de portabilité (du moment que le code marche
et sous Solaris et sous Linux), et j'ai besoins des écritures
synchronisées. On peut bien le faire avec un fstream, en prenant
des précautions nécessaires.
Plusieurs points importants :
-- L'ouverture en écriture seulement vide toujours le fichier,
s'il existe déjà. Il faut absolument ouvrir en
bidirectionnel, si tu veux y écrire, mais tu ne veux pas
détruire tout le contenu précédant.
-- Si tu veux utiliser seek pour aller à un endroit arbitraire,
il faut ouvrir en mode binaire ; sinon, tu n'as droit à
seeker qu'au deux bouts ou à un endroit où tu as fait un
tell.
-- Enfin, tu ne peux changer la taille du fichier qu'en
ajoutant des octets à la fin. Si tu veux remplacer un
enrégistrement dans le fichier, il faut que la taille du
remplacement soit identique à la taille de ce que tu
remplaces.
Donc, en supposant que tu saches déjà exactement où tu veux
écrire, le code devient quelque chose comme :
std::ofstream dest(
name, std::ios::in | std::ios::out | std::ios::binary ) ;
dest.seekp( position, std::ios::beg ) ;
// Sorties vers dest, en prenant bien soin du nombre
// des octets générés.
Note que ce dernier point argue fort en faveur de l'utilisation
d'un std::ostringstream pour le formattage, afin de pouvoir
contrôle très exactement le nombre d'octets écrits (avec par
exemple dest.write, plutôt que des opérateurs <<).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
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
j'ai besoin de remplacer un certain nombre d'octets à la fin d'un fichier. Comment procéderiez-vous? Faut-il utiliser un ofstream? Un ifstream?
La plupart du temps, dans de tels cas, j'utilise carrément l'interface Posix, avec des ostringstream pour formatter. Mais je n'ai pas besoin de portabilité (du moment que le code marche et sous Solaris et sous Linux), et j'ai besoins des écritures synchronisées. On peut bien le faire avec un fstream, en prenant des précautions nécessaires.
Plusieurs points importants :
-- L'ouverture en écriture seulement vide toujours le fichier, s'il existe déjà. Il faut absolument ouvrir en bidirectionnel, si tu veux y écrire, mais tu ne veux pas détruire tout le contenu précédant.
-- Si tu veux utiliser seek pour aller à un endroit arbitraire, il faut ouvrir en mode binaire ; sinon, tu n'as droit à seeker qu'au deux bouts ou à un endroit où tu as fait un tell.
-- Enfin, tu ne peux changer la taille du fichier qu'en ajoutant des octets à la fin. Si tu veux remplacer un enrégistrement dans le fichier, il faut que la taille du remplacement soit identique à la taille de ce que tu remplaces.
Donc, en supposant que tu saches déjà exactement où tu veux écrire, le code devient quelque chose comme :
std::ofstream dest( name, std::ios::in | std::ios::out | std::ios::binary ) ; dest.seekp( position, std::ios::beg ) ; // Sorties vers dest, en prenant bien soin du nombre // des octets générés.
Note que ce dernier point argue fort en faveur de l'utilisation d'un std::ostringstream pour le formattage, afin de pouvoir contrôle très exactement le nombre d'octets écrits (avec par exemple dest.write, plutôt que des opérateurs <<).
-- James Kanze (GABI Software) email: 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
Guillaume GOURDIN
-- L'ouverture en écriture seulement vide toujours le fichier, s'il existe déjà. Il faut absolument ouvrir en bidirectionnel, si tu veux y écrire, mais tu ne veux pas détruire tout le contenu précédant.
Effectivement, c'set que j'ai fait en premier et je ne comprenais pas pourquoi mon fichier était systématiquement vidé.
-- Si tu veux utiliser seek pour aller à un endroit arbitraire, il faut ouvrir en mode binaire ; sinon, tu n'as droit à seeker qu'au deux bouts ou à un endroit où tu as fait un tell.
Ah bon? En fait, ce que j'ai fait, c'est utilisé un fstream, que j'ouvre avec les flags par défaut (in et out, et il me semble que le mode binaire n'est pas activé) et j'arrive à faire des seek. Le code exact ressemble à ça :
Donc, en supposant que tu saches déjà exactement où tu veux écrire, le code devient quelque chose comme :
std::ofstream dest( name, std::ios::in | std::ios::out | std::ios::binary ) ; dest.seekp( position, std::ios::beg ) ; // Sorties vers dest, en prenant bien soin du nombre // des octets générés.
Ici quelle est la signification précise de 'std::ios::in'? Que l'on va faire des seek? Qu'il ne fait pas effacer le contenu du fichier?
Merci beaucoup.
-- L'ouverture en écriture seulement vide toujours le fichier,
s'il existe déjà. Il faut absolument ouvrir en
bidirectionnel, si tu veux y écrire, mais tu ne veux pas
détruire tout le contenu précédant.
Effectivement, c'set que j'ai fait en premier et je ne comprenais pas
pourquoi mon fichier était systématiquement vidé.
-- Si tu veux utiliser seek pour aller à un endroit arbitraire,
il faut ouvrir en mode binaire ; sinon, tu n'as droit à
seeker qu'au deux bouts ou à un endroit où tu as fait un
tell.
Ah bon? En fait, ce que j'ai fait, c'est utilisé un fstream, que j'ouvre
avec les flags par défaut (in et out, et il me semble que le mode
binaire n'est pas activé) et j'arrive à faire des seek. Le code exact
ressemble à ça :
Donc, en supposant que tu saches déjà exactement où tu veux
écrire, le code devient quelque chose comme :
std::ofstream dest(
name, std::ios::in | std::ios::out | std::ios::binary ) ;
dest.seekp( position, std::ios::beg ) ;
// Sorties vers dest, en prenant bien soin du nombre
// des octets générés.
Ici quelle est la signification précise de 'std::ios::in'? Que l'on va
faire des seek? Qu'il ne fait pas effacer le contenu du fichier?
-- L'ouverture en écriture seulement vide toujours le fichier, s'il existe déjà. Il faut absolument ouvrir en bidirectionnel, si tu veux y écrire, mais tu ne veux pas détruire tout le contenu précédant.
Effectivement, c'set que j'ai fait en premier et je ne comprenais pas pourquoi mon fichier était systématiquement vidé.
-- Si tu veux utiliser seek pour aller à un endroit arbitraire, il faut ouvrir en mode binaire ; sinon, tu n'as droit à seeker qu'au deux bouts ou à un endroit où tu as fait un tell.
Ah bon? En fait, ce que j'ai fait, c'est utilisé un fstream, que j'ouvre avec les flags par défaut (in et out, et il me semble que le mode binaire n'est pas activé) et j'arrive à faire des seek. Le code exact ressemble à ça :
Donc, en supposant que tu saches déjà exactement où tu veux écrire, le code devient quelque chose comme :
std::ofstream dest( name, std::ios::in | std::ios::out | std::ios::binary ) ; dest.seekp( position, std::ios::beg ) ; // Sorties vers dest, en prenant bien soin du nombre // des octets générés.
Ici quelle est la signification précise de 'std::ios::in'? Que l'on va faire des seek? Qu'il ne fait pas effacer le contenu du fichier?
Merci beaucoup.
James Kanze
On Apr 8, 11:22 am, Guillaume GOURDIN wrote:
-- Si tu veux utiliser seek pour aller à un endroit arbitraire, il faut ouvrir en mode binaire ; sinon, tu n'as droit à seeker qu'au deux bouts ou à un endroit où tu as fait un tell.
Ah bon? En fait, ce que j'ai fait, c'est utilisé un fstream, que j'ouvre avec les flags par défaut (in et out, et il me semble que le mode binaire n'est pas activé) et j'arrive à faire des seek.
C'est un comportement indéfini ; l'implémentation n'est pas obligé à signaler l'erreur, et peut bien même définir le comportement. Dans les fait, le flags binary est un no-op sous les Unix, et les seek marchent. Sous Windows, un seek dans un fichier texte ne provoque pas d'erreur, mais ne va pas forcément où tu veux.
Donc, en supposant que tu saches déjà exactement où tu veux écrire, le code devient quelque chose comme :
std::ofstream dest( name, std::ios::in | std::ios::out | std::ios::binary ) ; dest.seekp( position, std::ios::beg ) ; // Sorties vers dest, en prenant bien soin du nombre // des octets générés.
Ici quelle est la signification précise de 'std::ios::in'? Que l'on va faire des seek? Qu'il ne fait pas effacer le contenu du fichier?
Exacte. Aussi, il permet en principe la lecture. Seulement, dans l'interface de ofstream, il n'y a pas de fonction pour lire ; il faudrait donc récupérer le streambuf, et lire à travers lui.
Pour être plus précis (mais ça ne change rien à ton cas) : les flags d'ouverture n'ont aucun effet sur le ifstream, ofstream ou fstream, qui ne fait que les passer au filebuf. Que le flux même soit considérer en entrée, en sortie ou bi-directionnel dépend uniquement de son type (ifstream, ofstream ou fstream), et non des flags passés lors de la création ou l'ouverture. Il n'y a qu'un seul filebuf, en revanche, qui supporte toujours et les entrées et les sorties au niveau d'interface, quitte à renvoyer une erreur si tu essaies quelque chose non conforme aux flags d'ouverture. Du coup, il est même possible (mais sans le moindre intérêt) à connecter un filebuf ouverte uniquement pour l'écriture à un istream.
Pour des raisons historiques, il s'avère en plus que l'ouverture en écriture seulement tronque toujours, même si le flag ios::trunc n'est pas positionné. C-à-d : ios::out, ios::out | ios::trunc, et ios::in | ios::out | ios::trunc vident tous le fichier ; il faut bien ios::in | ios::out (sans ios::trunc) pour ne pas le vider. Ce n'est pas trop logique, mais c'est comme ça. (Note que le fopen de C n'est pas plus logique. Normalement, c'est "r" pour lire, et "w" pour écrire. Ajoute un "+", et ça devient bidirectionnel, avec "r+" pour ne pas vider, et "w+" pour vider.)
En gros, on peut dire que dans les deux cas (C et C++), le composant a été conçu pour lire ou écrire un flux de texte séquentiellement, avec l'écriture toujours vers un fichier neuf, et que les autres fonctionnalités sont venues s'y ajouter d'une façon plus ou moins ad hoc, et pas toujours très propre.
-- James Kanze (GABI Software) email: 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
On Apr 8, 11:22 am, Guillaume GOURDIN <tr...@hotmail.com> wrote:
-- Si tu veux utiliser seek pour aller à un endroit arbitraire,
il faut ouvrir en mode binaire ; sinon, tu n'as droit à
seeker qu'au deux bouts ou à un endroit où tu as fait un
tell.
Ah bon? En fait, ce que j'ai fait, c'est utilisé un fstream,
que j'ouvre avec les flags par défaut (in et out, et il me
semble que le mode binaire n'est pas activé) et j'arrive à
faire des seek.
C'est un comportement indéfini ; l'implémentation n'est pas
obligé à signaler l'erreur, et peut bien même définir le
comportement. Dans les fait, le flags binary est un no-op sous
les Unix, et les seek marchent. Sous Windows, un seek dans un
fichier texte ne provoque pas d'erreur, mais ne va pas forcément
où tu veux.
Donc, en supposant que tu saches déjà exactement où tu veux
écrire, le code devient quelque chose comme :
std::ofstream dest(
name, std::ios::in | std::ios::out | std::ios::binary ) ;
dest.seekp( position, std::ios::beg ) ;
// Sorties vers dest, en prenant bien soin du nombre
// des octets générés.
Ici quelle est la signification précise de 'std::ios::in'? Que
l'on va faire des seek? Qu'il ne fait pas effacer le contenu
du fichier?
Exacte. Aussi, il permet en principe la lecture. Seulement, dans
l'interface de ofstream, il n'y a pas de fonction pour lire ;
il faudrait donc récupérer le streambuf, et lire à travers lui.
Pour être plus précis (mais ça ne change rien à ton cas) : les
flags d'ouverture n'ont aucun effet sur le ifstream, ofstream ou
fstream, qui ne fait que les passer au filebuf. Que le flux même
soit considérer en entrée, en sortie ou bi-directionnel dépend
uniquement de son type (ifstream, ofstream ou fstream), et non
des flags passés lors de la création ou l'ouverture. Il n'y a
qu'un seul filebuf, en revanche, qui supporte toujours et les
entrées et les sorties au niveau d'interface, quitte à renvoyer
une erreur si tu essaies quelque chose non conforme aux flags
d'ouverture. Du coup, il est même possible (mais sans le moindre
intérêt) à connecter un filebuf ouverte uniquement pour
l'écriture à un istream.
Pour des raisons historiques, il s'avère en plus que l'ouverture
en écriture seulement tronque toujours, même si le flag
ios::trunc n'est pas positionné. C-à-d : ios::out, ios::out |
ios::trunc, et ios::in | ios::out | ios::trunc vident tous le
fichier ; il faut bien ios::in | ios::out (sans ios::trunc)
pour ne pas le vider. Ce n'est pas trop logique, mais c'est
comme ça. (Note que le fopen de C n'est pas plus logique.
Normalement, c'est "r" pour lire, et "w" pour écrire. Ajoute un
"+", et ça devient bidirectionnel, avec "r+" pour ne pas vider,
et "w+" pour vider.)
En gros, on peut dire que dans les deux cas (C et C++), le
composant a été conçu pour lire ou écrire un flux de texte
séquentiellement, avec l'écriture toujours vers un fichier neuf,
et que les autres fonctionnalités sont venues s'y ajouter d'une
façon plus ou moins ad hoc, et pas toujours très propre.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
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
-- Si tu veux utiliser seek pour aller à un endroit arbitraire, il faut ouvrir en mode binaire ; sinon, tu n'as droit à seeker qu'au deux bouts ou à un endroit où tu as fait un tell.
Ah bon? En fait, ce que j'ai fait, c'est utilisé un fstream, que j'ouvre avec les flags par défaut (in et out, et il me semble que le mode binaire n'est pas activé) et j'arrive à faire des seek.
C'est un comportement indéfini ; l'implémentation n'est pas obligé à signaler l'erreur, et peut bien même définir le comportement. Dans les fait, le flags binary est un no-op sous les Unix, et les seek marchent. Sous Windows, un seek dans un fichier texte ne provoque pas d'erreur, mais ne va pas forcément où tu veux.
Donc, en supposant que tu saches déjà exactement où tu veux écrire, le code devient quelque chose comme :
std::ofstream dest( name, std::ios::in | std::ios::out | std::ios::binary ) ; dest.seekp( position, std::ios::beg ) ; // Sorties vers dest, en prenant bien soin du nombre // des octets générés.
Ici quelle est la signification précise de 'std::ios::in'? Que l'on va faire des seek? Qu'il ne fait pas effacer le contenu du fichier?
Exacte. Aussi, il permet en principe la lecture. Seulement, dans l'interface de ofstream, il n'y a pas de fonction pour lire ; il faudrait donc récupérer le streambuf, et lire à travers lui.
Pour être plus précis (mais ça ne change rien à ton cas) : les flags d'ouverture n'ont aucun effet sur le ifstream, ofstream ou fstream, qui ne fait que les passer au filebuf. Que le flux même soit considérer en entrée, en sortie ou bi-directionnel dépend uniquement de son type (ifstream, ofstream ou fstream), et non des flags passés lors de la création ou l'ouverture. Il n'y a qu'un seul filebuf, en revanche, qui supporte toujours et les entrées et les sorties au niveau d'interface, quitte à renvoyer une erreur si tu essaies quelque chose non conforme aux flags d'ouverture. Du coup, il est même possible (mais sans le moindre intérêt) à connecter un filebuf ouverte uniquement pour l'écriture à un istream.
Pour des raisons historiques, il s'avère en plus que l'ouverture en écriture seulement tronque toujours, même si le flag ios::trunc n'est pas positionné. C-à-d : ios::out, ios::out | ios::trunc, et ios::in | ios::out | ios::trunc vident tous le fichier ; il faut bien ios::in | ios::out (sans ios::trunc) pour ne pas le vider. Ce n'est pas trop logique, mais c'est comme ça. (Note que le fopen de C n'est pas plus logique. Normalement, c'est "r" pour lire, et "w" pour écrire. Ajoute un "+", et ça devient bidirectionnel, avec "r+" pour ne pas vider, et "w+" pour vider.)
En gros, on peut dire que dans les deux cas (C et C++), le composant a été conçu pour lire ou écrire un flux de texte séquentiellement, avec l'écriture toujours vers un fichier neuf, et que les autres fonctionnalités sont venues s'y ajouter d'une façon plus ou moins ad hoc, et pas toujours très propre.
-- James Kanze (GABI Software) email: 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