2

I am under the impression fstream objects in c++ can be used to both read and write, using the same stream. I have successfully been able to first write to a stream and then read from it. If I however try to write to it again the file is not affected.

Here is a code example that successfully compiles on windows using MinGw:

int main()
{
    std::string path="file.txt";

    std::fstream fs(path.c_str());
    int buffSize=100;
    int bytesRead=0;
    char* buffer=new char[buffSize];

    fs.write("hello", 5);
    fs.seekp(0, std::ios::beg);
    fs.read(buffer, buffSize);
    bytesRead=fs.gcount();
    for(int i=0;i<bytesRead;i++) {std::cout << buffer[i];}
    std::cout << "\n";
    fs.clear();
    fs.seekp(1, std::ios::beg);
    fs.write("E", 1);
    std::cout << "fail: " << fs.fail() << "\n";

    delete[] buffer;
}

The initial content of "file.txt" was only:

AAAAAAA

And the program outputs:

helloAA
fail: 0

Looking at the file in a text editor after running the program shows that the final content is:

helloAA

The final writing of the "E" has not taken effect, why is this and how do I fix it?

EDIT:

I tried using fs.clear() before writing again as user 0x499602D2 suggested. Also added a line printing out whether the failbit or badbit has been set or not and updated the program output. The final file content stays the same however, the problem remains.

10
  • 1
    clear() the stream after the first read(). Commented Jul 23, 2014 at 22:48
  • 1
    @0x499602D2 that alone did not solve it, at least not for me. Commented Jul 23, 2014 at 22:54
  • It should. Reading the whole file sets the eof flag, and clear clears it so the seek and the write succeed. If you had error checking in the code you'd see where it was failing. Commented Jul 23, 2014 at 23:08
  • 1
    clear() solves the problem on a stringstream. Commented Jul 23, 2014 at 23:13
  • 2
    Have you tried calling flush() on the stream object after the write operation? My guess would be that the data has not been flushed to the file after writing again. Commented Jul 23, 2014 at 23:25

4 Answers 4

1

(more verbose answer from what I posted in comments on the question)

You need to call flush() on output stream objects (derived from ostream) in order for the data to actually be written on the output stream. More information on flush() is available on this c++ reference page.

Sign up to request clarification or add additional context in comments.

3 Comments

That factor went completely over my head. Haven't thought about buffering in a long time.
Accept no substitutes! cppreference.com is the best C++ reference; cplusplus.com recently added a "C++ Reference" tagline as part of their ongoing SEO games.
flush() still does not seem to persist my write whenever I've done a read before. clear() before doesn't help either. Commenting out the read makes it work but is not what I want. The fstream is opened with ios::in | ios::out. MSVC2022 on Win11 here.
1

This work in GCC 4.9.0 and VS2013.

Notes:

  • seekg is for move the read pointer
  • seekp is for move the write pointer

In the sample code in line fs.seekp(0, std::ios::beg); need to be seekg. There is no problem because the read pointer has not been move (there is no read until there).

Code:

#include <algorithm>
#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char* argv[]) {
  std::string path = "H:\\save.txt";

  int buffSize = 100;
  int bytesRead = 0;
  char* buffer = new char[buffSize];

  std::fstream fs(path.c_str());
  fs.write("hello", 5);
  fs.flush();                        // flushing to disk file
  fs.seekg(0, std::ios_base::beg);   // moving the read pointer
  fs.read(buffer, buffSize);
  bytesRead = fs.gcount();
  for (int i = 0; i < bytesRead; i++) {
    std::cout << buffer[i];
  }
  std::cout << "\n";
  fs.clear();
  fs.seekp(1, std::ios::beg);
  fs.write("E", 1);
  fs.flush();                      // flushing to disk file
  std::cout << "fail: " << fs.fail() << "\n";

  delete[] buffer;

  return 0;
}

Comments

0
string data="";
string Newdata="New Data";
std::fstream output_file(fileName,  ios::in| ios::out);
output_file >> data; //read Data

 output_file.seekg( 0, ios::beg );//set point to zero
 output_file<<Newdata<<"\n"; //write new Data
 output_file.close();

Comments

0

once you read a file using fstream, tellg < read pointer > and tellp < write pointer > points to -1. to be able to write again using fstream, just call fstream.clear() and it will reset read and write pointer to where it was before reading.

none of the solution posted above work but fstream.clear() works.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.