Hemant Bhargava
Hemant Bhargava

Reputation: 3585

std::getline with std::fstream

I am using std::fstream to read and write to the same file. I can see the write happening but not the read.

After searching the web, I got to know that I can not set in and app mode together. So, got rid of that and made it very simple of not passing any arguments.

I am very interested to know the reason why read is not happening.

Also, how do people read and write to the same file using same fstream?

My code:

#include<iostream>
#include<fstream>

int main() {
  std::fstream* fs = new std::fstream("xx.txt");
  *fs << "Hello" << std::endl;
  (*fs).close(); // ?

  std::string line;
  while(std::getline(*fs, line)) {
    std::cout << line << std::endl;
  }
}

With this code, I can xx.txt contain "Hello" as its content but it does not go inside the while loop at all stating that reading failed.

How can I overcome this?

Upvotes: 1

Views: 2753

Answers (2)

Nik
Nik

Reputation: 1334

I will try to explain the issue.

Statement std::fstream* fs = new std::fstream("xx.txt"); will open file if it exists in default mode "in|out" . If the file does not exist then the call to open from inside of constructor std::fstream will fail. And this can be checked by checking failbit using function fail(). So you will explicitly need to call 'open' to use the fstream object for data input. Note: the new file will not be created unless you call 'close'.

You can test this by actually trying to open an existing file or new file you can see the difference.

So alternatively what you should do is always call 'open' which will work in both cases (if file exists or not).

#include<iostream>
#include<fstream>


int main() {
    //std::fstream fs("xx.txt");
    //std::cout << fs.fail() << std::endl; // print if file open failed or passed
    std::fstream fs;  
    fs.open("xx.txt", std::fstream::in | std::fstream::out | std::fstream::app);
    std::cout << fs.fail() << std::endl;
    fs << "Hello" << std::endl;

    if (fs.is_open())
    {   
        std::cout << "Operation successfully performed\n";
        fs.close();
    }
    else
    {   
        std::cout << "Error opening file";
    }

For reading the content of the file you will first need to close the file. And then reopen and read. As I understand once you start using the object fs for insertion you cannot read from it unless you explicitly close it and reopen.

    fs.open("xx.txt", std::fstream::in | std::fstream::out);
    std::string line;
    while(std::getline(fs, line)) {
        std::cout << line << std::endl;
    }
    std::cout << "end" << std::endl;
    fs.close();
}

Upvotes: 1

Fareanor
Fareanor

Reputation: 6805

You forgot to reopen the stream. Actually you can't open a stream in both directions (at the same time).
So the steps are:

  • Open the stream for writing
  • Write data
  • Close the stream
  • Reopen the stream for reading
  • Read data
  • Close it (optional)

Your sample can be rewritten as:

#include <fstream>
#include <iostream>

int main()
{
    const std::string file_path("xx.txt");

    std::fstream fs(file_path, std::fstream::app);
    if(fs) // Check if the opening has not failed
    {
        fs << "Hello" << std::endl;
        fs.close();
    }

    fs.open(file_path, std::fstream::in);
    if(fs) // Check if the opening has not failed
    {
        std::string line;
        while(std::getline(fs, line))
        {
            std::cout << line << std::endl;
        }
        fs.close();
    }

    return 0;
}

Note that it is a good idea to check if the stream is successfully open before trying to use it.

Upvotes: 1

Related Questions