Un piège des opérateurs de flux (iostream : << >> read write)

Description

Lors de l'écriture de données numériques dans un fichier
il paraît très pratique d'utiliser les opérateurs suivants :
extraction de flux '>>' pour lire
insertion dans un flux '<<' pour écrire
L'utilisation de ces opérateurs comporte quelques pièges toutefois
Cet article se propose de donner des solutions à ces problèmes

PARTIE ECRITURE:
Supposons que nous voulions écrire des ints de valeurs 1, 10, 100 et 1000000000.
int iE1 = 1, iE10 = 10, iE100 = 100, iE1G = 1000000000;
On ouvre d'abord un fichier en écriture
ofstream out("temp.dat");
On insère ensuite nos valeurs :
out << iE1 << iE10 << iE100 << iE1G ; //utilisation d'écriture formatée
cout << "ecriture de " << iE1 << ", " << iE10 << ", " << iE100 << " et " << iE1G <<endl;
On referme le fichier :
out.close();
PARTIE RELECTURE:
Pour relire les variables stockées dans le fichier
int iL1 =0, iL10=0, iL100=0 , iL1G=0 ;
ifstream in("temp.dat");
in >> iL1 >> iL10 >> iL100 >> iL1G;
cout << "relecture de " << iL1 << ", " << iL10 << ", " << iL100 << " et " << iL1G <<endl;
On referme le fichier :
out.close();
RESULTAT:
ecriture de 1, 10, 100, 1000000000
relecture de ???, ???, ??? et ???

Explications supplémentaires dans le ZIP
Remarques bienvenues
Merci

Source / Exemple :


//Choisir soit SOLUTION 0, soit SOLUTION 1, soit SOLUTION 2
#define SOLUTION 0 // a modifier par 1 ou 2
//#define SOLUTION 1 //=> mode texte et "fin de ligne" avec << et >>
//#define SOLUTION 2 //=> mode binaire et "write+read" 

//Dans le cas de la SOLUTION 2 : activer
//#define DOUBLE_READ	// 1ere solution : directe
//#define BUFFER_MANUEL	// 2eme solution buffer manuel

#include <iostream>
#include <fstream>
using namespace std ;

int main(void){
	//écriture formatée et contrôlée ?
	int iE1 = 1, iE10 = 10, iE100 = 100, iE1G = 1000000000;
	float f1=1.1F, f2=2.2F;
	short sE1 = 1, sE10 = 10, sE100 = 100, sE1000 = 1000;
#if SOLUTION==0
	ofstream out("fic.dat"); 
	out << iE1 << iE10 << iE100 << iE1G ; //utilisation d'écriture formatée
	out << f1 << f2 ;
	out << sE1 << sE10 << sE100 << sE1000 ;
#elif SOLUTION==1
	ofstream out("fic.dat"); 
	out << iE1 << endl << iE10 << endl  << iE100 << endl  << iE1G << endl;
	out << f1 << endl << f2 << endl;
	out << sE1 << endl << sE10 << endl  << sE100 << endl  << sE1000 << endl;
#elif SOLUTION==2
	//écrire les valeurs directement
	ofstream out("fic.dat"/*, ios::binary*/); 
	//INT
	out.write(reinterpret_cast<char*>(&iE1),sizeof(&iE1));
	out.write(reinterpret_cast<char*>(&iE10),sizeof(&iE10));
	out.write(reinterpret_cast<char*>(&iE100),sizeof(&iE100));
	out.write(reinterpret_cast<char*>(&iE1G),sizeof(&iE1G));
	//FLOAT
	out.write(reinterpret_cast<char*>(&f1),sizeof(&f1));
	out.write(reinterpret_cast<char*>(&f2),sizeof(&f2));
	//SHORT
	#ifndef BUFFER_MANUEL
		out.write(reinterpret_cast<char*>(&sE1),sizeof(&sE1));
		out.write(reinterpret_cast<char*>(&sE10),sizeof(&sE10));
		out.write(reinterpret_cast<char*>(&sE100),sizeof(&sE100));
		out.write(reinterpret_cast<char*>(&sE1000),sizeof(&sE1000));
	#else
		char bufShort[4*2]; // 4:nbre de shorts, 2=sizeof(short)
		memcpy(bufShort, &sE1, 2);
		memcpy(bufShort+2, &sE10, 2);
		memcpy(bufShort+4, &sE100, 2);
		memcpy(bufShort+6, &sE1000, 2);
		out.write(bufShort,4*2);
	#endif
#endif
	cout << "ecriture 'int' de " << iE1 << ", " << iE10 << ", " << iE100 << " et " << iE1G <<endl;
	cout << "ecriture 'float' de " << f1 << " " << f2 << endl;
	cout << "ecriture 'short' de " << sE1 << ", " << sE10 << ", " << sE100 << " et " << sE1000 <<endl;

	out.close(); //Ferme le fichier et le flux

	int iL1 =-1, iL10=-1, iL100=-1, iL1G=-1 ;
	float fLu1=-1.F, fLu2=-1.F;
	short sL1 =-1, sL10=-1, sL100=-1 , sL1000=-1 ;
#if SOLUTION==2
	ifstream in("fic.dat"/*, ios::binary*/);
	//INT
	in.read(reinterpret_cast<char*>(&iL1), sizeof(iL1));
	in.read(reinterpret_cast<char*>(&iL10), sizeof(iL10));
	in.read(reinterpret_cast<char*>(&iL100), sizeof(iL100));
	in.read(reinterpret_cast<char*>(&iL1G), sizeof(iL1G));
	//FLOAT
	in.read(reinterpret_cast<char*>(&fLu1), sizeof(fLu1));
	in.read(reinterpret_cast<char*>(&fLu2), sizeof(fLu2));	  
	//SHORT
	#ifndef BUFFER_MANUEL
		in.read(reinterpret_cast<char*>(&sL1), sizeof(sL1));
		#ifdef DOUBLE_READ
			short bidon;
			in.read(reinterpret_cast<char*>(&bidon), sizeof(short));
		#endif
			in.read(reinterpret_cast<char*>(&sL10), sizeof(sL10));
		#ifdef DOUBLE_READ
			in.read(reinterpret_cast<char*>(&bidon), sizeof(short));
		#endif
			in.read(reinterpret_cast<char*>(&sL100), sizeof(sL100));
		#ifdef DOUBLE_READ
			in.read(reinterpret_cast<char*>(&bidon), sizeof(short));
		#endif
			in.read(reinterpret_cast<char*>(&sL1000), sizeof(sL1000));
	#else
		in.read(reinterpret_cast<char*>(&sL1), sizeof(sL1));
		in.read(reinterpret_cast<char*>(&sL10), sizeof(sL10));
		in.read(reinterpret_cast<char*>(&sL100), sizeof(sL100));
		in.read(reinterpret_cast<char*>(&sL1000), sizeof(sL1000));
	#endif	
#else
	ifstream in("fic.dat");
	in >> iL1 >> iL10 >> iL100 >> iL1G;
	in >> fLu1 >> fLu2;
	in >> sL1 >> sL10 >> sL100 >> sL1000;
#endif
	cout << "relecture 'int' de " << iL1 << ", " << iL10 << ", " << iL100 << " et " << iL1G <<endl;
	cout << "relecture 'float' de " << fLu1 << " " << fLu2 << endl;
	cout << "relecture 'short' de " << sL1 << ", " << sL10 << ", " << sL100 << " et " << sL1000 <<endl;

	in.close();

	return 0;
}

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.