LocustSpectre
LocustSpectre

Reputation: 87

Handling exception(s) with two file stream in C++

I'm building a program that handles input file and output file, with Visual Studio 2012.

I implemented like this:

ifstream inputFile;
ofstream outputFile;

inputFile.exceptions ( ifstream::failbit | ifstream::badbit );
try
{
    // some codes here
    inputFile.open(inputFileName.c_str());
    cout << "Input file opened" << endl;

    outputFile.open(outputFileName.c_str());
    cout << "Output file opened" << endl;
}
catch (ifstream::failure e)
{
    cerr << "Failed to open input file" << endl;
    return -1;
}
catch (ofstream::failure e)
{
    cerr << "Failed to open output file" << endl;
    return -1;
}   

And a compile error occurs:

error C2312: 'std::ios_base::failure' : is caught by 'std::ios_base::failure' at line 248

How do I implement try-catch with two sources of exception?

Upvotes: 0

Views: 398

Answers (2)

Massa
Massa

Reputation: 8972

As you can see, the types of the exceptions thrown are the same. But, as your checking is done so near the opening of the file, you can do it without exceptions, no? like:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
  string inputFileName { "/notexists" };
  string outputFileName { "/notexistsandprobablynotwritable" };
  ifstream inputFile { inputFileName };
  if( !inputFile ) {
    cerr << "Failed to open input file" << endl;
    return -1;
  }
  cout << "Input file opened" << endl;
  ofstream outputFile { outputFileName };
  if( !outputFile ) {
    cerr << "Failed to open output file" << endl;
    return -1;
  }
  cout << "Output file opened" << endl;
}

Or, if you really need the exceptions, you can throw different exceptions yourself, at the open site:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

template<typename Stream, typename Exception = typename Stream::failure>
  void try_open(Stream& s, string filename) {
      s.open(filename);
      if( !s )
        throw Exception( string("cannot open ")+filename );
  }

struct input_exception: ifstream::failure { input_exception(const string& s): ifstream::failure(s) {} };
struct output_exception: ofstream::failure { output_exception(const string& s): ofstream::failure(s) {} };

int main() {
  string inputFileName { "/notexists" };
  string outputFileName { "/notexistsandprobablynotwritable" };
  try {
    ifstream inputFile;
    try_open<ifstream, input_exception>(inputFile, inputFileName);
    cout << "Input file opened" << endl;
    ofstream outputFile;
    try_open<ofstream, output_exception>(outputFile, outputFileName);
    cout << "Output file opened" << endl;
  } catch(const output_exception& e) {
      cerr << "output exception!\n" << e.what() << "\n";
  } catch(const input_exception& e) {
      cerr << "input exception!\n" << e.what() << "\n";
  } catch(const exception& e) {
      cerr << "exception!\n" << e.what() << "\n";
  }
}

Upvotes: 0

jsantander
jsantander

Reputation: 5102

Your problem is that ifstream::failure and ofstream::failure are the same type (inherited to both of them from ios_base),

Since it is the same exception, the compiler complains.

BTW you should catch by const reference to avoid unneeded copies.

Upvotes: 3

Related Questions