Echec IO: on teste errno, comme en C ?

Le
Marc Boyer
Bonjour,

je débute avec les fichiers, et je me demandais comment
on faisait pour avoir la cause de l'erreur.

Je fais un
ofstream f("toto.txt");
if (!f.is_open()){
cerr<<"Impossible d'ouvrir toto.txt "<<strerrno(errno)<<endl;
}

Mais est-ce bien la C++-attitude ?

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Michael DOUBEZ
Le #307292
Bonjour,

je débute avec les fichiers, et je me demandais comment
on faisait pour avoir la cause de l'erreur.

Je fais un
ofstream f("toto.txt");
if (!f.is_open()){
cerr<<"Impossible d'ouvrir toto.txt "<<strerrno(errno)<<endl;
}

Mais est-ce bien la C++-attitude ?


En utilisant open() qui est susceptible de lancer une exception à
condition de l'avoir activer avant:
ofstream f;

// Lancer une exception si "failbit" ou "badbit" est levé
f.exceptions (ios::failbit | ios::badbit);

try
{// Open will throw on error
f.open ("toto.txt");
}
catch (exception &e)
{
cerr << "Impossible d'ouvrir toto.txt : " << e.what () << endl;
}

Le contenu du what() dépend de l'implémentation de la STL.

Michael

James Kanze
Le #307271
On May 14, 1:32 pm, Marc Boyer wrote:

je débute avec les fichiers, et je me demandais comment
on faisait pour avoir la cause de l'erreur.

Je fais un
ofstream f("toto.txt");
if (!f.is_open()){
cerr<<"Impossible d'ouvrir toto.txt "<<strerrno(errno)<<endl;
}

Mais est-ce bien la C++-attitude ?


Pourquoi pas ?

Formellement, la situation est exactement pareille qu'en C. La
fonction dit s'il a réussi ou non, mais la norme ne prévoit
aucune indication en ce qui concerne le pourquoi d'un échec.
Tout au plus permet-elle à l'implémentation de modifier errno,
sans pour autant l'exiger ni spécifier des valeurs qu'errno
pourrait éventuellement prendre. La spécification de
filebuf::open se réposant sur la spécification de fopen, dans la
norme C, on pourrait supposer peut-être que le comportement ici
en soit identique, mais je ne suis pas du tout sûr que la norme
C++ l'exige, ni même que c'en était l'intention de l'exiger.

Dans la pratique, sur des plateformes Unix et semblable, et
filebuf::open et fopen vont se réposer sur la fonction Posix
open, et c'est elle qui positionne en fait errno en cas
d'erreur. En revanche, je n'ai malheureusement pas d'expérence
sur ce sujet sous Windows ; je ne saurais donc dire si c'est
aussi le cas là que errno soit positionné. (En renvanche, je
serais très étonné que filebuf::open et fopen se comportent de
manière différente, quelque soit la plateforme.)

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

James Kanze
Le #307270
On May 14, 2:54 pm, Michael DOUBEZ
je débute avec les fichiers, et je me demandais comment
on faisait pour avoir la cause de l'erreur.

Je fais un
ofstream f("toto.txt");
if (!f.is_open()){
cerr<<"Impossible d'ouvrir toto.txt "<<strerrno(errno)<<endl;
}

Mais est-ce bien la C++-attitude ?


En utilisant open() qui est susceptible de lancer une exception à
condition de l'avoir activer avant:
ofstream f;

// Lancer une exception si "failbit" ou "badbit" est levé
f.exceptions (ios::failbit | ios::badbit);

try
{// Open will throw on error
f.open ("toto.txt");}

catch (exception &e)
{
cerr << "Impossible d'ouvrir toto.txt : " << e.what () << endl;
}


C'est un peu tordu d'utiliser des exceptions dans ce cas-ci,
non ?

Le contenu du what() dépend de l'implémentation de la STL.


Parmi les quatre auxquels j'ai accès, j'ai :
"basic_ios::clear" (g++),
"iostream object has failbit set" (Sun CC/Rogue Wave),
"ios failure" (Sun CC/STL port), and
"ios_base::failbit set" (VC++/Dinkumware).
J'ai comme un petit soupçon qu'il voulait plus d'information que
ça.

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


Marc Boyer
Le #307269
Le 15-05-2007, James Kanze
Parmi les quatre auxquels j'ai accès, j'ai :
"basic_ios::clear" (g++),
"iostream object has failbit set" (Sun CC/Rogue Wave),
"ios failure" (Sun CC/STL port), and
"ios_base::failbit set" (VC++/Dinkumware).
J'ai comme un petit soupçon qu'il voulait plus d'information que
ça.


Heu, oui...
Le strerror(ernno) est bien plus parlant quand même.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)

Marc Boyer
Le #307268
Le 15-05-2007, James Kanze
On May 14, 1:32 pm, Marc Boyer wrote:

je débute avec les fichiers, et je me demandais comment
on faisait pour avoir la cause de l'erreur.

Je fais un
ofstream f("toto.txt");
if (!f.is_open()){
cerr<<"Impossible d'ouvrir toto.txt "<<strerrno(errno)<<endl;
}

Mais est-ce bien la C++-attitude ?


Pourquoi pas ?


Je sais pas. Je demande. C'est la première fois depuis
longtemps que j'inclus un .h dans mon code C++.
Je me demandais s'il n'y avait pas une surcouche C++.

Formellement, la situation est exactement pareille qu'en C. La
fonction dit s'il a réussi ou non, mais la norme ne prévoit
aucune indication en ce qui concerne le pourquoi d'un échec.
Tout au plus permet-elle à l'implémentation de modifier errno,
sans pour autant l'exiger ni spécifier des valeurs qu'errno
pourrait éventuellement prendre.


Ca, je comprends bien: les systèmes de fichiers étants
variés, il seraient difficile de spécifier tous les messages
d'erreur. Mais dans la pratique, errno/strerror/perror
s'en sortent bien.

Dans la pratique, sur des plateformes Unix et semblable, et
filebuf::open et fopen vont se réposer sur la fonction Posix
open, et c'est elle qui positionne en fait errno en cas
d'erreur. En revanche, je n'ai malheureusement pas d'expérence
sur ce sujet sous Windows ; je ne saurais donc dire si c'est
aussi le cas là que errno soit positionné. (En renvanche, je
serais très étonné que filebuf::open et fopen se comportent de
manière différente, quelque soit la plateforme.)


Merci pour les renseignements,
Marc Boyer


--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)


Marc Boyer
Le #307267
Le 15-05-2007, Michel Decima
On May 14, 2:54 pm, Michael DOUBEZ
En utilisant open() qui est susceptible de lancer une exception à
condition de l'avoir activer avant:
ofstream f;

// Lancer une exception si "failbit" ou "badbit" est levé
f.exceptions (ios::failbit | ios::badbit);

try
{// Open will throw on error
f.open ("toto.txt");}

catch (exception &e)
{
cerr << "Impossible d'ouvrir toto.txt : " << e.what () << endl;
}


C'est un peu tordu d'utiliser des exceptions dans ce cas-ci,
non ?


Je trouve aussi. Et il faudrait penser a nettoyer les drapeaux
d'exception apres l'ouverture, si on veut garder un comportement
"classique" des flux, au moins en lecture.


Oui, j'avais encapsulé le tout dans une fonction try_open
qui refaisait un f.exceptions( ios::goodbit) après
l'ouverture.
Mais vu la pauvreté des messages d'erreur, je fais aussi
un
cerr<<strerror(errno)
dans le catch...

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. André Maurois)



Michel Decima
Le #307266
On May 14, 2:54 pm, Michael DOUBEZ
En utilisant open() qui est susceptible de lancer une exception à
condition de l'avoir activer avant:
ofstream f;

// Lancer une exception si "failbit" ou "badbit" est levé
f.exceptions (ios::failbit | ios::badbit);

try
{// Open will throw on error
f.open ("toto.txt");}

catch (exception &e)
{
cerr << "Impossible d'ouvrir toto.txt : " << e.what () << endl;
}


C'est un peu tordu d'utiliser des exceptions dans ce cas-ci,
non ?


Je trouve aussi. Et il faudrait penser a nettoyer les drapeaux
d'exception apres l'ouverture, si on veut garder un comportement
"classique" des flux, au moins en lecture. Le code suivant
se termine par une exception, meme si le fichier est present:

std::ifstream f;
f.exceptions( ios::failbit | ios::badbit );

try {
f.open( "toto.txt" );
std::string line;
while ( getline( f, line ) ) {
std::cout << line << "n";
}
}
catch ( std::exception& e ) {
std::cerr << "Exception: " << e.what() << std::endl;
}


Alain Gaillard
Le #307265
En revanche, je n'ai malheureusement pas d'expérence
sur ce sujet sous Windows ; je ne saurais donc dire si c'est
aussi le cas là que errno soit positionné.


Sous Windows c'est forcément différent ;)
Au niveau du système, tu dois appeler l'API GetLastError pour savoir ce
qui s'est passé.
Mais pour le peu de fois où j'ai eu à m'en servir, avec un compilateur
Borland, le runtime fournissait bien une variable globale errno qu'il se
charge de remplir. Donc à priori on peut bien coder de la même façon
avec errno sous Windows et Unix.

--
Alain

Michael DOUBEZ
Le #307264
On May 14, 2:54 pm, Michael DOUBEZ
En utilisant open() qui est susceptible de lancer une exception à
condition de l'avoir activer avant:
ofstream f;

// Lancer une exception si "failbit" ou "badbit" est levé
f.exceptions (ios::failbit | ios::badbit);

try
{// Open will throw on error
f.open ("toto.txt");}

catch (exception &e)
{
cerr << "Impossible d'ouvrir toto.txt : " << e.what () << endl;
}


C'est un peu tordu d'utiliser des exceptions dans ce cas-ci,
non ?


Je trouve aussi. Et il faudrait penser a nettoyer les drapeaux
d'exception apres l'ouverture, si on veut garder un comportement
"classique" des flux, au moins en lecture. Le code suivant
se termine par une exception, meme si le fichier est present:


Je suis d'accord que, vu l'inutilité des messages, l'activation de
l'exception est superflu.
C'est dommage que l'exception lancée par open() n'inclue pas un champ
errno (à défaut d'avoir un message plus informatif).

Peut être dans ce cas, refaire un filebuf qui lance une exception
personnalisé en utilisant les fonctions POSIX.

Michael



James Kanze
Le #307263
On May 15, 10:57 am, Michael DOUBEZ
On May 14, 2:54 pm, Michael DOUBEZ
En utilisant open() qui est susceptible de lancer une exception à
condition de l'avoir activer avant:
ofstream f;

// Lancer une exception si "failbit" ou "badbit" est levé
f.exceptions (ios::failbit | ios::badbit);

try
{// Open will throw on error
f.open ("toto.txt");}

catch (exception &e)
{
cerr << "Impossible d'ouvrir toto.txt : " << e.what () << endl;
}


C'est un peu tordu d'utiliser des exceptions dans ce cas-ci,
non ?


Je trouve aussi. Et il faudrait penser a nettoyer les drapeaux
d'exception apres l'ouverture, si on veut garder un comportement
"classique" des flux, au moins en lecture. Le code suivant
se termine par une exception, meme si le fichier est present:


Je suis d'accord que, vu l'inutilité des messages, l'activation de
l'exception est superflu.
C'est dommage que l'exception lancée par open() n'inclue pas un champ
errno (à défaut d'avoir un message plus informatif).


C'est dommage que les iostream en général, et les fstream en
particulier, ne donne pas plus d'informations en ce qui concerne
la source d'une erreur. Dans certains cas, c'est même impossible
à savoir s'il y a eu une erreur de format sur la dernière
entrée.

Peut être dans ce cas, refaire un filebuf qui lance une exception
personnalisé en utilisant les fonctions POSIX.


Pourquoi toujours les exceptions ? Rien n'empêche filebuf
d'avoir des fonctions supplémentaires, dont une pour indiquer le
type de la dernière erreur vue.

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




Publicité
Poster une réponse
Anonyme