nthfiles

closed account (jvqpDjzh)
I have been studying files for a while, but actually we see so many different things on the web to do (it seems) the same thing sometimes. Many people suggest to do a thing, others another one. I would like to know the unforgettable rules to apply always to files, in what circumstances, ecc. For example:

0. Of course we have always to close the file. (I don't mention explicitly the opposite).
1. Is always a good programming practice to control if a file is open (with the function is_open())?
2. If we control if a file is open, should we control also if it's good or is not bad, or something like that?
3. To get all the file content, we can use getline, until the eofbit is not set, but is it the best thing to do?

Well, we see many things like that around the web, but what are the best programming practices to manage files?

Thank you!
Last edited on
0. We do not have to close C++ file streams because they are closed automatically in destructor. However we cannot check if file is there was an error during closing that way.

1. Yes. It is a good practice. Because file might be not here, you do not have permisssions, etc.

2. C++ fsream is that: a stream. Anything applying to generic streams (including cin and cout) applies to file streams too. It is always a good idea to check stream state.

3. getline was not created to get all file content, and in case of generic binary file it cannot be used that way. Depending on purpose you might select different strategies, but in general case you do not want whole file (which can be gygabites in size) in memory. .read() member function is usually used.


You should always remember that with files more things can go wrong: there could not be enough space, you can have unsufficient permissions, file can be locked by AV software or deleted by user in process.
Also streams are buffered, so in case your program crashes you are not guaranteed that everything you written to this point will be actually written (and in case of some filesystems that file will be actually here)
closed account (jvqpDjzh)
But do you suggest to always use the try-catch construct when we are talking about managing files or there's a situation where the try-catch is unnecessary?
Is this correct for example?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//Is this function really useful?
bool exists(std::string fname = "")
{
    std::ifstream in(fname);
    if(in)
    {
        in.close();
        return true;
    }
    else return false;
}

void ReadFile(std::string path = "")
{

    if(!exists(path))
    {
        try
        {
            std::ofstream ofile(path);
            if(ofile.is_open())
            {
                for(int i=0; i<10; i++) ofile << i <<'\n';
                ofile.close();
            }
        }
        catch(const std::ios_base::failure& ex)
        {
            std::cout << ex.what()<<'\n';
        }
    }
    else
    {
        try
        {
            std::string content = "";
            std::ifstream file(path);
            file.seekg(0, file.beg);//this is not necessary
            if(file.is_open())
            {
                char c = ' ';
                while( (c = file.get()) != EOF ) std::cout << c;
                file.close();
            }
        }
        catch(const std::ios_base::failure& ex)
        {
            std::cout << ex.what()<<'\n';
        }
    }
}

streams generally do not throw exceptions at all. You should tell them so beforhand. Usually checking for fail/bad bit after input is enough.
Is this correct for example?

No, it's not. Generally speaking, having streams throw exceptions on failure is not a good thing to have happen, so they don't do it by default.

Since, you didn't tell your streams that they should throw, they will not throw.

http://en.cppreference.com/w/cpp/io/basic_ios/exceptions
closed account (jvqpDjzh)
So my program would be correct if I added this: ofile.exceptions(std::ofstream::failbit); right?

having streams throw exceptions on failure is not a good thing to have happen, so they don't do it by default.
you recommend just to use the default version and check for fail/bad bit?
Last edited on
you recommend just to use the default version and check for fail/bad bit?
Usually, yes.
Many operations sets failbit as part of their normal function. There is sense in setting program to throw exception on badbit because usually it is fatal error in depth of implementation and is usually unrecoverable.
closed account (jvqpDjzh)
So something like this should be good?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        try
        {
            std::string content = "";
            std::ifstream file(path);
            file.exceptions(std::ifstream::badbit);
            if(file.is_open() && file.good())
            {
                char c = ' ';
                while( (c = file.get()) != EOF && !file.fail() )
                    std::cout << c;
                file.close();
            }
        }
        catch(const std::ios_base::failure& ex)
        {
            std::cout << "bad_bit"<<'\n';
        }
8
9
10
char c;
while( ( file.get(c) )
    std::cout << c;
Also your code will not generate exception if babbit was set while opening file.
Last edited on
closed account (jvqpDjzh)
Also your code will not generate exception if babbit was set while opening file.
So I have to set it before opening:
1
2
3
 std::ofstream ofile;
            ofile.exceptions(std::ofstream::badbit);
            ofile.open(path);


Last edited on
Nope, just open it in constructor and check it manually.
Also default constructor of ofstream sets badbit too.

So do not bother with exceptions with streams aside from specific cases.
closed account (jvqpDjzh)
Ok, thanks again!
Topic archived. No new replies allowed.