fstream using formatted data

698 views Asked by At

i am new to this site , and this my first question ! i have a question about fstream function .

fstream f("new.dat",ios::out|ios::in);

fstream is for both input and output , so when we use it like this , and there is a new.dat file before it will output and input both . but it is strange , when i do that , it will output data correctly , but it is unable to input . i found out if you close it , and reopen it , it will input . why it is like that??

int main()
{
    fstream writeFile("newFile.dat", ios::out|ios::in);
    char i[3];
    char u[3]="HI";
    if (!writeFile)
    {
        cerr << "error" << endl;
    }
    writeFile << u <<endl;
    writeFile >> i;
    cout << i << endl;
}

this is my full code , and result is an empty line.

2

There are 2 answers

0
jaggedSpire On BEST ANSWER

The fstream object has a position in its output file, and since you opened it just for output and input without any position or writing modifiers, that position is at the end of the file. When you output i to the file, writeFile writes i to the file, and then moves its position past i so when you ask it to write more, you don't overwrite i.

You can reset the position to the start of the file with a call to writeFile.seekg(0), which places that internal position at the 0 position in the file (at the start).

If you're curious about stream manipulation, I'd suggest a look at cppreference.com and specifically its documentation on c++'s input and output libraries here.

0
user4581301 On

Couple things going on here:

  1. You can't open a file for reading if it doesn't exist, this includes a file you want to read and write. No file, no open.
  2. Once you manage to open a file, the stream keeps track of where it is in the file. As you read or write, obviously the location moves.
  3. There is only one location marker in the stream, so you can read to where you want to write, then write. Unfortunately this means any further reading will pick up after the write. If that's not what you want, get and store the current location (with tellg) before writing, and seek (with seekg) to the stored location after writing.
    1. This has some problems such as what if the block of data you wish to insert is longer or shorter than the block of data you want to overwrite? The simple solution to this problem is read into buffer, edit buffer, write buffer back to file.
  4. When you open a file and start writing into it, you overwrite whatever was in the file. If you want to add to a file, open with ios::app. This sets the stream's location to the end of the file. I am unaware of any sort of insert that pushes existing data along as you write in new data.

Some simple file handling example code

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

int main()
{
    fstream f1("filename", ios::out);
    if (f1.is_open())
    {
        if (f1 << "Hi")
        {
            cout << "wrote"<<endl;
        }
        f1.close();
    }
    fstream f2("filename", ios::out|ios::app);
    if (f2.is_open())
    {
        if (f2 << " there!")
        {
            cout << "appended"<<endl;
        }
        f2.close();
    }
    fstream f3("filename", ios::in);
    if (f3.is_open())
    {
        cout << f3.rdbuf()<< endl;
        f3.close();
    }

    fstream f4("filename", ios::in|ios::out);
    if (f4.is_open())
    {
        f4.seekg(3);
        if (f4 << "Fred!")
        {
            cout << "overwrote"<<endl;
        }
        f4.close();
    }

    fstream f5("filename", ios::in);
    if (f5.is_open())
    {
        cout << f5.rdbuf()<< endl;
        f5.close();
    }
// note the extra ! on the end left over from Hi there! I do not know how
// to get rid of this. I have always just done stuff like this to get around it.
    fstream f6("filename", ios::in);
    stringstream s1;
    string token;
    f6 >> token;
    s1 << token << " Tim!";
    f6.close();
    fstream f7("filename", ios::out);
    f7 << s1.rdbuf();
    f7.close();
// and then moved temp over filename.
    fstream f8("filename", ios::in);
    cout << f8.rdbuf()<< endl;
    f8.close();

}