8
votes

Pourquoi STD :: Copie (d'Istream à Ostream) soulève une exception IOS :: Échec de l'échec?

Le code suivant doit copier des données d'un wifstream vers wcout. Une fois que le contenu est copié, le programme jette une exception IOS :: échecs.

#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include <locale>
#include <iterator>
#include <algorithm>


int main(void)
{
    std::locale::global(std::locale(""));

    std::wifstream is;
    is.exceptions( std::ios::failbit | std::ios::badbit );
    is.open("test.ts", std::ios::binary);

    is >> std::noskipws;

    std::istream_iterator<wchar_t, wchar_t> in(is);
    std::istream_iterator<wchar_t, wchar_t> end;

    std::copy(in, end,
              std::ostream_iterator<wchar_t, wchar_t>(std::wcout));

    return 0;
} 


1 commentaires

Définir des exceptions de flux semble être une bonne idée, mais cela ne fonctionne souvent pas comme vous vous attendez. Au lieu de cela, vérifiez simplement l'état du flux avant d'utiliser l'entrée, par exemple. if (flux >> var) {/ * utilisez uniquement Var * /} .


3 Réponses :


2
votes

Pour éviter de sauter de l'espace blanc Utilisez le std :: istreambuf_itéator xxx pré>

L'exception: p>

La locale peut utiliser la facette Codecvt qui échoue.
Essayez de commenter la ligne locale Voir ce qui se passe. P>

Avez-vous essayé d'imprimer quelles sont les exceptions? P>

try
{
    // do work
}
catch(std::exception const& e)
{
    std::cout << e.what() << "\n";
}


3 commentaires

C'est beau, mais le Noskippws ne provoque pas l'exception. Même si je le décompte, il y a une exception.


Il y a une faute de frappe, le deuxième argument à Istreambuf_iterator est une classe de trait.


Le message d'exception est: basic_ios :: Effacer et même si je supprimais la localisation globale, l'exception est lancée.



1
votes

parce que vous utilisez std :: istream_iterator code>, la tentative de lecture d'un caractère au-delà de l'extrémité du flux définit les deux eofbit code> et échecbat code > (Et seulement après que certains bits d'erreur sont définis, l'itérateur est-il égal à l'itérateur final)

Stripping à des essentiels nus et à revenir à un caractère pour le rendre encore plus simple, le programme est équivalent à: P>

#include <iostream>
#include <fstream>
int main()
{
    std::ifstream is("test.txt", std::ios::binary);
    is.exceptions(std::ios::failbit); // failbit only because that's what you get
    is >> std::noskipws;
    if(is)
        for(char c; is >> c;) // will throw!
            std::cout << c;
}


2 commentaires

Pas assez équivalent, mais ce serait: pour (char c; est >> c;) COUT << C;


@Roger Pate aussi loin que je comprends, std :: copier n'exécutera pas opérateur >> même une fois si le flux est déjà en échec (et l'itérateur d'entrée est déjà égal. à l'itérateur final) donc tandis que (est).



0
votes

Selon le §27.6.1.2.3 / 10:

Une fois qu'un objet sentiné est construit, un caractère est extrait de dans , si l'on est disponible et stocké dans c . Sinon, la fonction appelle in.Setate (écheckit) .

Donc, lorsqu'il atteint la fin du fichier et ne peut plus extraire un caractère, il définira le bit d'échec, que vous avez défini pour produire une exception. En utilisant std :: copier ne change pas le comportement - un istream_itéator lit via opérateur >> .

vous Peut copier le fichier un peu plus facilement: xxx


3 commentaires

Cela n'a aucun sens pour moi. Si le Streambuf Streambuf retourne TRAITS_TYPE :: EOF (), le flux ne doit définir que le bit EOF, pas le bit d'échec.


Si cela indique que opérateur >> reviendrait sans tentative de conversion si le bit EOF a été défini, cela se produirait - mais cela ne le ferait pas. Même si le bit EOF est défini, il tente toujours une conversion, ce qui échoue, de sorte que le bit d'échec est défini.


@cytrinox: Eofbit est défini, puis opt >> causes échecs à définir.