Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::copy (from istream to ostream) raises an ios::failure exception?

Tags:

c++

stream

stl

The following code should copy data from an wifstream to wcout. After the content is copied, the program throws a ios::failure exception.

#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;
} 

The stream should only throw an exception (see exception mask) if anything goes bad, but not on EOF.

like image 509
cytrinox Avatar asked Nov 04 '10 17:11

cytrinox


People also ask

What is std :: ostream?

The std::ostream , the std::istream or the std::iostream are base classes of stream types (e.g. std::stringstream , std::fstream , etc.) in the Standard Library.

Is Istream part of Iostream?

istream and ostream serves the base classes for iostream class. The class istream is used for input and ostream for the output.


2 Answers

To avoid skipping white space use the std::istreambuf_iterator

std::copy(std::istreambuf_iterator<wchar_t, wchar_t>(is),
          std::istreambuf_iterator<wchar_t, wchar_t>(),
          std::ostream_iterator<wchar_t, wchar_t>(std::wcout));

The exception:

The local may be using codecvt facet that is failing.
Try commenting out the locale line see what happens.

Have you tried to print what the exceptions is?

try
{
    // do work
}
catch(std::exception const& e)
{
    std::cout << e.what() << "\n";
}
like image 172
Martin York Avatar answered Sep 20 '22 04:09

Martin York


Because you're using std::istream_iterator, the attempt to read a character past the end of the stream sets both eofbit and failbit (and only after some error bits are set, does the iterator become equal to the end iterator)

Stripping to bare essentials and reverting to char to make it even simpler, program is equivalent to:

#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;
}
like image 22
Cubbi Avatar answered Sep 20 '22 04:09

Cubbi