Create a file, read from it, then write to it

Hi, I'm learning some stuff about file streams.

What is the best way to create a file (if it doesn't exist), then read from it, then write to it?

Doing fstream only works if the file already exists.

1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
    std::fstream f;
    f.open("count.dat");
    if (!f.is_open())
    {
        //This runs when count.dat does not exist yet.
        std::cout << "Error opening file..." << std::endl;
        return -1;
    }   else std::cout << "File opened." << std::endl;
    f.close();
}

In the code above, using std::fstream only works if count.dat already exists.
To actually make a file, it appears that I have to use std::ostream.

Here's the full code:
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
#include <iostream>
#include <fstream>
#include <cstdlib>

/**
 * Keeps track of how many times this program has run,
 * using count.dat as a source of "memory" for it.
 */
int main()
{
    std::fstream f;
    f.open("count.dat");
    if (!f.is_open())
    {
        std::cout << "Error opening file..." << std::endl;
        return -1;
    }   else std::cout << "File opened." << std::endl;
   
    std::string line = "";
    int n = 0; //initialized to zero, in case first time running the file.
    
    while(getline(f, line))
    {
        std::cout << "Line: " << line << std::endl;
        n = std::stoi( line );
        //n = atoi(line.c_str()); 
    }
    f.clear();  //Resets EOF so that it can write again
    f.seekg(0); //Resets reading file back to index 0
    
    n++;
    f << n;
    f.close();

    return 0; 
}

In the code above, count.dat will either be empty, or have an integer number in it.

Can anyone give me a good way to make it so the above code will *create* count.dat if it does not already exist, but still be able to read and write to it?

Also, it's not important, but why does my program not return -1 after it displays "Error opening file..."? It says it returned with some junk 42929...whatever value.
Last edited on
closed account (j3Rz8vqX)
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
#include <iostream>
#include <fstream>
using namespace std;
void readWrite(string str)
{
    cout<<str;
    fstream file;
    file.open("count.dat", ios::out|ios::in);//Attempt to open file.
    if(file.is_open())
    {
        cout<<"Reading\n";
        string temp;
        while(getline(file,temp) && cout<<temp<<'\n');//Print data in file!
    }
    else
    {
        cout<<"Writing\n";
        file.open("count.dat", ios::out|ios::in|ios::trunc);//TRUNCATING to make new file!
        file<<"Hello World!\nThis is a string!";
    }
    file.close();//File must be properly closed if opened! Else issues may arise.
}
int main()
{
    cout<<"File Reading/Writing Program: \n";
    readWrite("\nFirst attempt!\n");
    readWrite("\nSecond attempt!\n");

    cout<<"\nPress <enter> to exit console: ";
    cin.get();
    return 0;
}
File Reading/Writing Program:

First attempt!
Writing

Second attempt!
Reading
Hello World!
This is a string!

Press <enter> to exit console:
Ah, so you just have to open it twice with different params, no getting around that. Thanks a lot.
closed account (j3Rz8vqX)
Not necessarily, does it have to open twice:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>
using namespace std;
void readWrite(string str)
{
    cout<<str;
    fstream file;
    file.open("count.dat", ios::out|ios::in|ios::trunc);//TRUNCATING to make new file!
    file<<"Hello World!\nThis is a string!";
    file.close();//File must be properly closed if opened! Else issues may arise.
}
int main()
{
    cout<<"File Reading/Writing Program: \n";
    readWrite("\nFile was created!\n");

    cout<<"\nPress <enter> to exit console: ";
    cin.get();
    return 0;
}
//count.dat
Hello World!
This is a string!

But rather the parameter ios::trunc creates the file even if existing.

IOS parameters:
http://msdn.microsoft.com/en-us/library/aa243822(v=vs.60).aspx
Last edited on
For a config file, that would always clear the file before trying to read from it, so your first solution of calling file.open() twice is still the better one.

Anyway, here's my final working program, in case anyone wanted to see it:
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
#include <iostream>
#include <fstream>
#include <cstdlib>

/**
 * Keeps track of how many times this program has run,
 * using count.dat as a source of "memory" for it.
 */
int readWrite(std::string filename)
{
    std::fstream f;
    f.open(filename);
    if (!f.is_open()) //File has not been created!
    {
        std::cout << filename << " not found. Creating..." << std::endl;
        f.open(filename, std::ios::out|std::ios::in|std::ios::trunc);
        if (!f.is_open())
        {
            std::cout << "Error creating file " << filename << "!" << std::endl;
            f.close(); //Is this necessary since the is_open() returns false?
            return -1;
        }
        f << 1; //This program has been run one time since creation of count.dat
    }
    else //File already exists, meaning it has a number in it
    {
        int n = 0;
        std::string line;
        while(std::getline(f, line))
        {
            //n = std::stoi(line);
            n = atoi(line.c_str()); 
        }   n++;
        f.clear();
        f.seekg(0);
        f << n; 
    }
    f.close();
    return 0;
}

int main()
{
    std::string filename = "count.dat";
    if (readWrite(filename) == 0)
    {
        std::cout << "count.dat" << " sucessfully incremented!" << std::endl;
    }   else std::cout << "There was some error...";
    
    return 0;
}

If you see anything "evil" about it, feel free to say something, otherwise, thanks again.
Last edited on
Topic archived. No new replies allowed.