Catching an exception for input and output file - c++

I open two files, one input and one output. I'd like to handle exceptions for both of them, so by looking at some examples, I made this:
std::ifstream readFile;
readFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
//set the flags for stream bits that indicate failure if ON
std::ofstream writeFile;
writeFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
try{
readFile.open(inputFileName);
writeFile.open(outputFileName);
function(readFile, writeFile);
readFile.close();
writeFile.close();
}
catch(std::ifstream::failure &readErr) {
std::cerr << "\n\nException occured when reading a file\n"
<< readErr.what()
<< std::endl;
return -1;
}
catch(std::ofstream::failure &writeErr) {
std::cerr << "\n\nException occured when writing to a file\n"
<< writeErr.what()
<< std::endl;
return -1;
}
This seems like a reasonable solution, but I get a warning:
warning: exception of type 'std::ios_base::failure' will be caught [enabled by default]
catch(std::ofstream::failure &writeErr) {
^
The code does it's thing, but I'm still interested in improving my code. Where have I wronged?

No you can't. The typedef of std::ifstream::failure and std::ofstream::failure are both defined to be std::ios_base::failure.
The best thing you could do is wrap the individual calls with try-catch:
try
{
readFile.open(inputFileName);
}
catch(std::ifstream::failure &readErr)
{
}
try
{
writeFile.open(outputFileName);
}
catch(std::ofstream::failure &writeErr)
{
}
Or check the state of the streams individually in the catch block to see who failed.

The only way to handle exceptions from the two files separately would be to catch the exception and then check the failbit on the streams to determine which of them that failed:
try
{
readFile.open(inputFileName);
writeFile.open(outputFileName);
function(readFile, writeFile);
readFile.close();
writeFile.close();
}
catch (const std::ios_base::failure &err)
{
if (readFile.fail())
{
std::cerr << "\n\nException occured when reading a file\n"
<< readErr.what()
<< std::endl;
}
if (writeFile.fail())
{
std::cerr << "\n\nException occured when writing to a file\n"
<< writeErr.what()
<< std::endl;
}
return -1;
}

Related

C++ Exception handling: exception vs. ifstream::failure

In which cases do Options 1 and 2 give different results/behaviour?
Are they equivalent in all respects?
I tried with a non-existing in_out/sample2.txt to force an exception and they behave the same.
int main() {
string fnamein2 = "in_out/sample2.txt";
ifstream ifstr;
try {
cout << "Reading " << fnamein2 << endl;
ifstr.open(fnamein2);
ifstr.exceptions( ifstream::eofbit | ifstream::failbit | ifstream::badbit );
} catch(const exception &e) { // <-- Option 1
//} catch(const ifstream::failure &e) { // <-- Option 2
cout << "There was an error: " << e.what() << endl;
}
return 0;
}
There is no difference in your scenario.
std::ifstream::failure is specialized version of std::exception (contains more details) but in your case you do not used them.
std::ifstream::failure has code method which gives you more information about an error. But if you do not need it, you can use base class.

File read fails with ios_base::failbit

I have a simple C++ file read program:
int main() {
std::string buf;
std::ifstream file;
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
file.open("C:\\Test11.txt");
char c;
while (!(file.eof())) {
file.get(c);
std::cout << c;
}
}
catch (std::ifstream::failure e) {
std::cout << e.what() << std::endl;
std::cout << e.code() << std::endl;
std::cout << "Exception opening/reading file";
}
file.close();
return 0;
}
The content of file at C:\Test11.txt is Hello.
The program is able to read the content but fails with exception ios_base::failbit. It seems to have problem while evaluating while (!(file.eof())).
What is going wrong?
The issues is that eof() is not true until you attempt to read past the end of file.
So once you have correctly read the whole of the file and there is no data left in the file. The result of eof() is still false (as you have not read past the end). It is the next read that will set eof() but it is also the next read that will fail (and thus throw an exception).
This is why checking for eof() is an anti-pattern.
while (!(file.eof()))
{
file.get(c);
std::cout << c;
}
The better (correct) pattern is:
while (file.get(c)) // reads next character into c returns a ref to file.
// Note: when a stream is used in a boolean context
// such as an while () it is converted to bool
// using !good(). Thus if the read fails
// and the bad bit is set and the loop will exit.
{
std::cout << c;
}

Crash when removing a QTemporaryFile

I convert QFile into FILE* to use some third-part libraries. Here is code:
QTemporaryFile pack200_file;
//Here write something into pack200_file
......
pack200_file.seek(0);
int handle_in = pack200_file.handle();
if (handle_in == -1)
{
qCritical() << "Error reopening " << pack200_file.fileName();
return false;
}
FILE * file_in = fdopen(handle_in, "r");
if(!file_in)
{
qCritical() << "Error reopening " << pack200_file.fileName();
return false;
}
QTemporaryFile qfile_out;
if(!qfile_out.open())
{
qCritical() << "Error opening " << qfile_out.fileName();
return false;
}
int handle_out = qfile_out.handle();
if (handle_out == -1)
{
qCritical() << "Error opening " << qfile_out.fileName();
return false;
}
FILE * file_out = fdopen(handle_out, "w");
if (!file_out)
{
qCritical() << "Error opening " << qfile_out.fileName();
return false;
}
try
{
unpack_200(file_in, file_out);
}
catch (std::runtime_error &err)
{
qCritical() << "Error unpacking " << pack200_file.fileName() << " : " << err.what();
return false;
}
//success
QString finalJarname = .....;
QFile::remove(finalJarname);
QFile::copy(qfile_out.fileName(), finalJarname);
fclose(file_in);
fclose(file_out);
qfile_out.remove(); //Here I got crash
pack200_file.remove();
return true;
I got crash at the line qfile_out.remove();, It seems the remove operation cause it. But I got nothing from trace stack and visual studio do not mention me which code trigger the crash finally.
If I change the code into:
fclose(file_in);
fclose(file_out);
qfile_out.setAutoRemove(false);
pack200_file.setAutoRemove(false);
qfile_out.close();
pack200_file.close();
return true;
it will also crash when return ;
Then I change IDE into QtCreator, it said:
Second Chance Assertion Failed: File
f:\dd\vctools\crt\crtw32\lowio\close.c , Line 47
Expression: (_osfile(fh) & FOPEN)
But I can't find the file f:\dd\vctools\crt\crtw32\lowio\close.c.
How can I localize the source of the crash?
You closed qfile_out's file for it with fclose(). Looks like the Visual C runtime library didn't like that, hence the exception. Suggest you remove the calls to fclose... or avoid mixing Qt and non-Qt file operations.

File not opening with C++ fstream even with full path

string mapFile;
cout << "Enter the file name : ";
cin >> mapFile;
ifstream mapfh;
mapfh.open(mapFile.c_str());
if(mapfh.is_open()) { ... }
else //if board file did not open properly
{
throw;
}
mapfh.close();
I am compiling with g++ in the command line. Whenever I put a file input (even with a full path i.e. /User/...etc./file.txt) it throws an error. I know the input is good, but for whatever reason the open always fails.
This isn't fully portable, but you'll get a more informed output if you interpret the errno,
#include <cerrno>
#include <cstring>
...
if(mapfh.is_open()) { ... }
else //if board file did not open properly
{
std::cout << "error: " << strerror(errno) << std::endl;
throw;
}
And if your policy is to communicate the errors as exceptions then use iostreams native support for the exceptions:
ifstream mapfh;
mapfh.exceptions(std::ios::failbit);
try {
mapfh.open(mapFile.c_str());
...
mapfh.close();
} catch (const std::exception& e) {
std::cout << e.what() << " : " << std::strerror(errno) << std::endl;
}

Unexpected results on exception while doing file I/O

I have a small code with some file I/O
bool loadConfigFile(std::string configFileName)
{
std::ifstream configFile;
try
{
configFile.open(configFileName, std::ifstream::in);
if(true != configFile.good())
{
throw std::exception("Problem with config file");
}
} catch (std::exception &e)
{
fprintf(stderr, "There was an error while opening the file: %s\n %s\n" , configFileName, e.what());
configFile.close();
}
configFile.close();
return true;
}
And everytime I launch the program without the file provided as a parameter I get some rubbish on output (random characters) or an unexpected error in runtime. What am I doing wrong here ?
"%s" expects an null terminated char array as its input but the code is passing configFileName, which is a std::string. Either use std::string::.c_str() or use std::cerr instead:
std::cerr << "There was an error while opening the file: "
<< configFileName << '\n'
<< e.what() << '\n';
Note that the ifstream constructor has a variant that accepts the filename to open and the destructor will close the stream if it is open so the explicit calls to open() and close() can be omitted:
try
{
std::ifstream configFile(configFileName);
if (!configFile.is_open())
{
throw std::exception("Failed to open '" + configFileName + "'");
}
}
catch (const std::exception& e)
{
// Handle exception.
std::cerr << e.what() << '\n';
return false;
}