Update ifstream object after data is written to its file using ofstream - c++

While testing my code, I faced an issue, that ifstream doesn't get updated when more data is written to its file. So here is a sample code that demonstrates the problem:
ifstream is(filename);
string line;
while (getline(is, line))
cout << "line: " << line << endl;
ofstream os(filename, ofstream::out | ofstream::app);
string additional("additional");
os << additional;
os.flush();
while (getline(is, line))
cout << "line additional: " << line << endl;
No additional lines were written to stdout, though they are written to the file.
I'm not using fstream instead of a couple of if/ofstream because I need it like this for testing purposes.
How to make ifstream "see" the changes in the file?
UPDATE: I cleared the bits using clear method. It works OK on my Ubuntu machine with gcc. But it doesn't work on my Mac OSX with llvm. Do you know how to do it platform independently?

You need to call std::ios::clear on the input stream after the first read.
When you read the whole file, it sets the failbit in the stream and will refuse to keep reading, even if the file actually changed in the meantime.
ifstream is(filename);
string line;
while (getline(is, line))
cout << "line: " << line << endl;
ofstream os(filename, ofstream::out | ofstream::app);
string additional("additional");
os << additional;
os.flush();
is.clear(); //< Now we can read again
while (getline(is, line))
cout << "line additional: " << line << endl;

When you hit the end of the file while reading is the first time, it sets the eofbit in the stream's internal error state.
You need to clear it before you can continuing reading, by calling the is.clear() function, which resets the internal error state.

I think the reason is that you have opened output stream file using "ofstream::out"
ofstream os(filename, ofstream::out | ofstream::app);
now, the "ofstream::out" truncates the file as soon as it opens it. That is, all the previous contents of your file will be deleted once it is opened. Please try using this instead:
ofstream os(filename, ios::app);

Related

Why is there delay when I write on a file using c++?

I've tried to open a file, write something on it, read from the file and do the same process again but the output isn't what I expect, here's the code:
file.open("ciao.txt", std::ios::out);
file << "ciao";
file.close();
file.open("ciao.txt", std::ios::out | std::ios::in);
std::string str;
std::getline(file, str);
cout << str;
file.seekp(0);
file << "addio";
std::getline(file, str);
cout << str;
The expected oputput is "ciao addio", but it only gives me "ciao". I've tried to run it line after line, but the file is edited as soon as the program stops. Can someone help please? I couldn't find anything online ;-;
The problem is a combination of things.
Here you write ciao to the file, no problem - except it doesn't have a newline (\n).
file << "ciao";
Later, you read a line:
std::getline(file, str);
Had there been a \n in the file, EOF would not have been reached and the fstream would still be in good shape for accepting I/O. Now it's not however.
So, either file.clear() after the getline or add a newline to the first output:
file << "ciao\n";
You also need to file.seekg(0); before the last getline.
file.open("ciao.txt", std::ios::out);
file << "ciao";
file.close();
file.open("ciao.txt", std::ios::out | std::ios::in);
std::string str;
std::getline(file, str);
file.clear(); // add this
cout << str;
file.seekp(0);
file << "addio";
file.seekg(0); // add this
std::getline(file, str);
// I added > and < to make it clear what comes from the file:
cout << '>' << str << "<\n";
Output:
ciao>addio<

How to save and also read c++ fstream file without closing it

I opened a file both read and write mode
using the following statement
file.open(fileName, ios::in | ios::out | ios::trunc);
my main purpose for opening the file in both mode is, read and write the file at the same time.
But In my code scenario,
when I am reading the file after writing it, the ouput showing blank that means,
it is not saving my writing contents because I am not closing it.
And I want to close the file after finishing both write and read the operation
I found a solution in Stack Overflow,
to use flush() function to save the file without closing
file.flush();
but, the problem is it's not working for my case
So, how can I save c++ fstream file without closing?
Here's my full code for better understanding
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main(int argc, char const *argv[])
{
string fileName = "text.txt";
fstream file;
file.open(fileName, ios::in | ios::out | ios::trunc);
if (file.is_open())
{
file << "I am a Programmer" << endl;
file << "I love to play" << endl;
file << "I love to work game and software development" << endl;
file << "My id is: " << 1510176113 << endl;
file.flush(); // not working
}
else
{
cout << "can not open the file: " << fileName << endl;
}
if (file.is_open())
{
string line;
while(file)
{
getline(file, line);
cout << line << endl;
}
}
else
{
cout << "can not read file: " << fileName << endl;
}
file.close();
return 0;
}
Actually, if you want to save any file immediately without closing the file, then you can simply use
file.flush();
But if you are want to read the file without closing just after writing it, you can simply use
file.seekg(0);
actually seekg() function resets the file pointer at the beginning, for this, it is not mandatory to save the file. so, this has nothing to with flush() function
but you can do both if you want to
Before reading from that file you need to make sure to place the pointer to that file to the beginning of the file. After writing to the file it'll point to the end. Therefore you won't be able to read anything.
You need to use file.seekg(0); somewhere after the file.flush() but before starting to read to place the file pointer to the very beginning.
Update
This should work without the flush. However this will depend on the implementation of the std library. Although I'd consider this as bug if it doesn't work without calling flush() imho it does not hurt to call it explicitly.

Why is getline (from a file) to cout (that line) not printing the line?

This is my code here.
ifstream inFile;
ofstream outFile;
string line, line2;
inFile.open("DATA.txt");
outFile.open("DATA.txt");
getline(inFile, line);
cout << line;
getline(inFile, line2);
cout << line2;
getline(cin, line);
getline(cin, line2);
outFile << line << "\n" << line2;
From what I understand, getline(inFile, line) should assign the first line of my text file to a string named line. Then the cout << line should print that string into the cmd window. This is not working though.
I am able to input just fine using getline(cin, line) and outFile though. The file gets updated and I can see what I typed in it, but it just doesn't properly read and print the lines.
p.s This is my first question and I'm not entirely sure how to ask it in the title so I'm open to criticism.
On most platforms, std::cout typically buffers output data and does not flush to the console until a line break is output, or the buffer is flushed explicitly.
Try using:
cout << line << '\n';
Or:
cout << line << endl;
If you don't want to output line breaks, use:
cout << line << flush;
So I figured it out. When I had
inFile.open("DATA.txt");
outFile.open("DATA.txt");
I think the outFile.open overwrote the inFile.open, causing only the output part to work.
Simply moving the outFile.open to before the output part instead of before everything fixed this problem. I'm sure there are several other sloppy things about my code, but that fixed it to the point of actually working.

ifstream not working with variable parameter using C++11 and c_str() appended

Note: I am using the C++11 standard, so I don't see why this isn't working with or without c_str() appended.
I have the following code:
// open streams
ifstream in(input);
ofstream out(output);
// get which file to open
in.ignore(INT_MAX, ':'); // we don't need the beginning part
in.ignore(); // remove trailing whitespace
string fileLocation;
getline(in, fileLocation);
out << "Loading: " << fileLocation << endl;
cout << "Loading: " << fileLocation << endl;
// now that we know where the file is, load it:
ifstream file(fileLocation);
which reads from a file that looks vaguely like this
File: file.txt
(Subcommands below)
I know that I am pulling the correct filename because of the terminal output.
Anyway, I noticed that the stream wasn't opening properly, so I added this conditional to check:
if ( !file )
{
cout << "File wasn't loaded properly." << endl;
}
And sure enough, I see that message when running the program.
My question is this: how come, when I hard-code the file location, e.g. ifstream file("file.txt") it opens up no problem? How do I get this working properly?

Problems with reading a .txt file

I am looking for an answer to my question, but i didn't find it in any other place.
I'm trying to read from a .txt file, that is located in the same directory as my project files.
I wrote this simple code:
ifstream file("file.txt");
std::string line;
std::getline(file, line);
cout << line;
...but unfortunately, nothing happened, not even an error or crashing.
Upon exploring a little further... even if I change the name of the txt("file") file, to the name of a file that doesn't exist, nothing happens.
What am I missing?
How do you know there were no errors? You did not check.
#include <cerrno>
and then
ifstream file("file.txt");
if (file) // is the file readable?
{
std::string line;
if (std::getline(file, line)) // did we manage to read anything?
{
cout << line;
}
else
{
cout << "File IO error";
}
}
else
{
cout << "error opening file: " << strerror(errno);
}
performs rudimentary checking.
if your error is due to opening file then provide full path to the file and check.
in your code you are reading the first line so if it is a white space then you can see nothing as output.
you must to iterate over each line until the last line (reaching the end of file EOF).
// let's say your file is "test.txt" which is located in D\\MyDB
// ifstream file("file.txt");
ifstream file("D:\\MyDB\\test.txt"); // use full path instead and check manully whether the file is there or not
std::string line;
if(file.fail())
cout << "Opening file failed!" << endl;
else
while(std::getline(file, line))
{
cout << line;
}
if it works when providing the full path then your current path is not the same as your project.
you can change the current directory using some API so if you are on windows then use: SetCurrentDirectory(path); and on linux use: chdir(sDirectory.c_str());
** I mean compilers not OS