Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

déplacer un morceau de fichier de taille connue

27 réponses
Avatar
Marc G
je voudrais savoir si mon code est correct, où s'il existe une autre méthode
file_ est un fstream


size_t size=500;
char* ptr=new char[size];
the_file.read(ptr,size);

// je me balade dans le fichier à l'endroit où je veux écrire

the_file.write(ptr,size);
delete[] ptr;

merci à vous
Marc

7 réponses

1 2 3
Avatar
James Kanze
On Nov 14, 10:40 am, Michael DOUBEZ wrote:
J'aimerais être sûr d'avoir compris ce que tu as dit: tu veux dire que
readsome ne lira pas dans le fichier mais uniquement dans le buffer
associé ?


S'il y a des caractères dans le buffer, il les lit, et rien
d'autre. S'il n'y en a pas, il finit, après un certain nombre
d'indirections, à lire selon ce que lui dit
streambuf::showmanyc(). Dont le comportement est défini par
l'implémentation. (Selon la norme, il renvoie 0, mais << An
implementation might well provide an overriding definition for
this function signature if it can determine that more characters
can be read from the input sequence. >> (On a bien l'impression
que cette partie de la norme a été écrite par un normand.)

Ma compréhension était que readsome ne levait pas eofbit quand
il arrivait a la fin du fichier mais a part cela etait
équivalent à un read et gcount dans le cas d'un fichier.


Il peut aussi lever eofbit (et failbit, aussi, si eofbit est
déjà actif), si in_avail() renvoie -1 (c-à-d que in_avail sait
qu'il n'y aurait plus de caractères).

Le but de readsome, si j'ai bien compris, c'est d'être une
espèce de lecture non-bloquant ; il renvoie les caractères
qu'il a, mais il ne bloque pas en lecture s'il n'en a pas. À
mon avis, il n'a aucune utilité pour les flux standard. Si tu
implémente un socketbuf, en revanche, il pourrait bien avoir une
utilité : dans showmanyc(), ton socketbuf polle le socket, et
lit ce qu'il y a de disponible. (On pourrait aussi imaginer des
implémentations où il avait une utilité avec un clavier. Mais il
faudrait plus qu'un filebuf classique -- sous Unix, par
exemple, il faudrait qu'il active O_NDELAY et O_NONBLOCK avant
d'appeler read.)

Il n'a aucune utilité sur un fichier classique (ni, évidemment,
sur un stringstream).

--
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

Avatar
James Kanze
On Nov 14, 10:41 am, Jean-Marc Bourguet wrote:
James Kanze writes:
On Nov 13, 9:06 pm, Jean-Marc Bourguet wrote:
Michael DOUBEZ writes:
je voudrais savoir si mon code est correct, où s'il existe une a utre
méthode
file_ est un fstream
size_t sizeP0;
char* ptr=new char[size];
the_file.read(ptr,size);


Utilises gcount() pour connaitre le nombre d'octet
effectivement lus ou utilises readsome()?


Pourquoi utiliser readsome dans ce contexte?


Sans doute pour la même raison que beaucoup de gens utilisent
rdbuf()->in_avail() : parce qu'ils en ont mal compris la
sémantique.


Si au moins in_avail retournait egptr() - gptr() + showmanyc()


Il appelle showmanyc() si egptr() - gptr() est 0. C'est le cas
important : tu boucles sur l'appelle de readsome tant qu'il ne
renvoie pas 0, et tu finis par avoir tous les caractères
disponibles.

(La flemme de regarder, comment showmanyc interagit avec les
mapping CR/LF->LF? Mal je suppose pour rendre encore la chose
encore moins utilisable.)


Utiliser readsome() (ou in_avail()) sur un fichier n'a pas
réelement de sens. Si le fichier n'est pas sensé grandir (le cas
le plupart du temps), une lecture n'en serait jamais
<< bloquante >> ; ou bien, tu lis des caractères, ou bien tu as
fin de fichier. Et si tu t'attends à ce que le fichier grandit
(comme dans << tail -f >> sous Unix), tu aurais probablement
quand même ton fin de fichier, quand il n'y a rien à lire.

--
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





Avatar
James Kanze
On Nov 14, 11:01 am, Michael DOUBEZ wrote:

James Kanze writes:

On Nov 13, 9:06 pm, Jean-Marc Bourguet wrote:
Michael DOUBEZ writes:
je voudrais savoir si mon code est correct, où s'il existe une aut re
méthode
file_ est un fstream
size_t sizeP0;
char* ptr=new char[size];
the_file.read(ptr,size);
Utilises gcount() pour connaitre le nombre d'octet

effectivement lus ou utilises readsome()?
Pourquoi utiliser readsome dans ce contexte?

Sans doute pour la même raison que beaucoup de gens utilisent

rdbuf()->in_avail() : parce qu'ils en ont mal compris la
sémantique.


Si au moins in_avail retournait egptr() - gptr() + showmanyc()

(La flemme de regarder, comment showmanyc interagit avec les mapping
CR/LF->LF? Mal je suppose pour rendre encore la chose encore moins
utilisable.)


Est ce que read fait la conversion CR/LF->LF ?


Pas sur ma machine Linux:-).

Dans la philosophie des iostream, il y a trois << conversions >>
distinctes :

-- Au plus bas niveau, et uniquement dans filebuf, dans la
norme, il y a deux types de flux, binaire et texte. Un flux
texte, c'est en fait une suite de lignes. Interne, une
<< ligne >>, c'est une suite de caractères imprimables,
terminés par un 'n'. Dans un fichier, tout dépend de
l'OS. Sous Unix/Linux, il n'y a rien à faire, parce que la
convention interne correspond exactement à la convention de
l'OS (comme par hazard). Sous Windows, la convention n'est
pas claire, et différents programmes agissent
différemment : les compilateurs C++ que je connais utilise
la convention qu'une ligne est *terminée* par un CRLF (mais
beaucoup d'autres programmes utilisent la convention que des
lignes sont separées par des CRLF). Sur de gros IBM, la
convention est qu'une ligne est un enrégistrement, et chaque
fois tu écris un 'n', l'implémentation écrit un
enrégistrement (sans aucun caractère pour la fin de la
ligne).

Il y a aussi des conventions concernant des blancs à la fin
d'une ligne (qu'une implémentation peut ignorer) et la fin
de fichier, aussi bien en mode texte qu'en mode binaire.
(Sous Windows, la plupart des implémentations reconnaît un
0x1A dans un fichier texte comme fin de fichier, pour des
raisons historiques.)

Comme j'ai dit, tout ça, c'est au plus bas niveau, et dépend
uniquement de la façon que tu as ouvert le fichier (et donc
ne peut pas changer une fois le fichier ouvert).

-- Ensuite, aussi uniquement dans filebuf, mais indépendamment
de la mode d'ouverture du fichier, il y a une conversion de
l'encodage par le locale imbué dans le filebuf (qui peut
être différent de celui imbué dans le istream ou le ostream,
si tu as fait un << in.rdbuf()->imbue() >>, par exemple). Si
tu veux être sûr qu'il n'y a aucune transformation à ce
niveau, il faut prendre soin d'imbuer le locale "C".

-- Enfin, il y a le formattage ou le parsing : on convertit
entre une représentation texte et une représentation
interne. C'est la seule conversion qui a lieu dans les
istream et les ostream : il a lieu avec tous les << et >>,
et non avec les autres fonctions.

L'important, ici, c'est de se rendre compte que ces trois
conversions ont lieu de façon indépendamment l'une de l'autre.
La conversion des 'n' et des fins de fichier dépend uniquement
de la mode d'ouverture du fichier. Le transcodage dépend
uniquement du locale imbué. Et que tu formattes/parses ou non
dépend uniquement de ce que tu te sers de <</>> ou d'une
fonction nommée.

--
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






Avatar
James Kanze
On Nov 14, 10:59 am, Michael DOUBEZ wrote:
On Nov 13, 9:06 pm, Jean-Marc Bourguet wrote:
Michael DOUBEZ writes:
je voudrais savoir si mon code est correct, où s'il existe une autr e
méthode
file_ est un fstream
size_t sizeP0;
char* ptr=new char[size];
the_file.read(ptr,size);


Utilises gcount() pour connaitre le nombre d'octet
effectivement lus ou utilises readsome()?


Pourquoi utiliser readsome dans ce contexte?


Sans doute pour la même raison que beaucoup de gens utilisent
rdbuf()->in_avail() : parce qu'ils en ont mal compris la
sémantique.


in_avail() retourne le nombre de caractères pouvant être lut
par read sans bloquer. Je ne vois pas en quoi c'est
incompatible avec readsome sur un fichier, le nombre de
caractères pouvant être lut etant bien ceux entre le curseur
courant et la fin du fichier.


Et comment déterminer ce nombre ? Je sais le faire sous Unix,
et dans des fichiers ouverts en binaires prèsque partout, mais
je ne sais pas le faire dans le cas général.

Selon la norme, si le buffer est vide, in_avail() sur un filebuf
renvoie 0. Avec un commentaire (<< remark >>) qu'une
implémentation pourrait faire mieux, si l'information est
disponible. Des quatres implémentations ici, si j'ouvre un
fichier (en mode texte), puis appelle in_avail() immediatement,
deux renvoient la taille du fichier, et deux renvoient 0.

Comme par hazard, les deux qui renvoient la taille du fichier
sont tous les deux sous Unix. Comme j'ai dit ci-dessus, je ne
sais pas déterminer une valeur correct sauf sous Unix. (Le g++
sous CygWin retourne aussi la taille du fichier. Mais le g++
sous CygWin ne sait pas lire des fichiers en mode texte.)

streamsize readsome(char_type* s, streamsize n);

Effects: If !good() calls setstate(failbit) which may throw an
exception, and return. Otherwise extracts characters and stores them
into successive locations of an array whose first element is designated
by s . If rdbuf()->in_avail() == -1, calls setstate(eofbit) (which may
throw ios_base::failure (lib.iostate.flags)), and extracts no characters;

* If rdbuf()->in_avail() == 0, extracts no characters

* If rdbuf()->in_avail() > 0, extracts min(rdbuf()->in_avail(),n)).


Oui. Tout dépend de in_avail. Ce qui dépend ensuite de
showmanyc(). Qui dépend de l'implémentation, mais qui renvoie,
par défaut, 0.

--
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





Avatar
James Kanze
On Nov 15, 7:38 am, "Marc G" wrote:
Je connais exactement la structure du fichier.


Je me doutais un peu. C'est généralement le cas quand on veut se
positionner dans un fichier.

Quand je lis une grosse structure (avec de nombreux appels à
read), je trouve lourd de vérifier le nombre d'octects lus à
chaque fois.


C'est le but de read(). La lecture réussit ou non. Si elle
réussit, tu as lu ce que tu voulais. Si elle ne réussit pas,
c'est une erreur.

Note aussi que si tu veux positionner à des endroits précis,
determinés par un calcul numérique, et non simplement faire des
retours en arrière à des endroits déjà visités, il faut ouvrir
le fichier en binaire.

Qu'est-ce qui se passe dans le code suivant si la lecture de x
échoue ? y-a-t-il une exception lors de la tentative de
lecture de y, ou la fonction ne fait simplement rien compte
tenu de l'état du flux ?

input.read((char*)&x,sizeof(x));
input.read((char*)&y,sizeof(y));


Ça dépend de ce que tu as démandé, mais par défaut, la deuxième
appel ne ferait rien si le premier a échoué. (Tu peux, en
revanche, démander à ce que le flux lève des exceptions en cas
d'erreur.)

je préfèrerait vérifier l'état du flux une fois pour toutes à
la fin (sachant que normalement il n'y a jamais de problème !)


C'est l'utilisation habituelle, au moins pour les flux en
sortie. Pour les flux en entrée, il faut quand même vérifier
l'état avant d'utiliser les données lues.

autre question :

operator !() est surchargé pour fstream (entre-autres)
est-ce que operator bool() est surchargé de la même manière (mon com pilateur
l'accepte) , ie
if (input) ...
équivaut à
if (!!input)
?


Non. Ce qui est surchargé, en revanche, c'est une conversion en
void*, qui fonctionne comme un bool. (On n'a pas voulu
surcharger une conversion en bool, parce que bool se convertit
implicitement en int, et des opérateurs >> et << sont défini
pour les entiers. Du coup, une petite erreur de codages, et on
peut avoir des résolutions de surcharge surprenantes, plutôt que
l'erreur de compilation qu'on aimerait.)

--
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

Avatar
James Kanze
On Nov 15, 7:38 am, "Marc G" wrote:

[...]
input.read((char*)&x,sizeof(x));
input.read((char*)&y,sizeof(y));


Encore un point, en passant : si tu as besoin du cast (et
l'utilisation de sizeof suggère fort que c'est le cas), ton code
ne marcherais pas dans la plupart des cas. Tu ne peux pas
simplement dumper l'image d'un objet en mémoire et s'attendre à
quelque chose d'utilisable.

--
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

Avatar
Marc G
merci pour tes conseils avisés
Marc
1 2 3