0

In example below, file exceptions are set. Inside the try-catch block is validating the size of the read data using the gcout() function. Is it necessary to test the return value of gcount() when the exceptions are set?

#include <iostream>
#include <fstream>

int main()
{
    char buf[100];
    std::ifstream file;

    file.exceptions(std::ios_base::badbit | std::ios_base::failbit | std::ios_base::eofbit);

    try {
        file.open("file.bin", std::ios_base::in | std::ios_base::binary);

        file.read(buf, sizeof buf);

        // Is this error check redundant?
        if (file.gcount() != sizeof buf) {
            std::cout << "gcount(): Read error\n";
        }

        file.close();
    } catch (...) {
        std::cout << "Exception: Read error\n";
    }

    return 0;
}
Kam
  • 211
  • 1
  • 8
  • 3
    File I/O operations do not throw by default in C++, so you can't catch anything - you want to check the return values of the open(), read() and other functions. –  Jul 31 '19 at 16:44
  • 3
    Yes, I know. But I did not ask the default case. I asked the case in my example where I set up exceptions on reading/writing. – Kam Jul 31 '19 at 16:49
  • 1
    The open() call won't throw an exception if you set the exception mask after the call. –  Jul 31 '19 at 17:02
  • [Related](https://stackoverflow.com/questions/9670396/exception-handling-and-opening-a-file) –  Jul 31 '19 at 17:53

2 Answers2

1

The fact that read() throws an exception at all guarantees that gcount() cannot be equal to the requested buffer size. You can look at gcount() after a successful read() to check how many bytes it actually read, which you know is not the case if an exception is thrown.

In your example, you have set an exception to be thrown on all possible outcomes of read() that do not read the entire requested size. So yes, in that case, checking gcount() is redundant. It would only make sense to check gcount() if EOF were reached with no exception thrown, and you want to know how many bytes were read. Which doesn't make a lot of sense for a binary read, unless the data is variable-length and you simply just don't know its size up front. If you need to handle data that ends with EOF, you shouldn't be throwing an exception on eofbit to begin with. Throw an exception on EOF only if EOF is a real error condition (ie, the data at the end of the stream is incomplete).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Correct, the stream exception function is passed a std::ios_base::iostate parameter of type trait BitmaskType. Bitmask types supports all bitwise operators:

The bitwise operators operator&, operator|, operator^, operator~, operator&=, operator|=, and operator^= are defined for values of the bitmask type and have the same semantics as the corresponding built-in operators on unsigned integers would have if the bitmask elements were the distinct integer powers of two.

Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • My English is not good. I will try ask other way. My question is: Is it necessary to test the return value of gcount() when the exceptions are set? – Kam Jul 31 '19 at 17:25