Why is there delay when I write on a file using c++? - 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<

Related

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.

C++ why is my file truncating when I restart my program?

I'm trying to use this code to read from the file and store values in a vector. This works once and displays everything correctly.
void SongList::LoadSongsFromFile()
{
song temp;
string line;
ifstream myFile("SongListFile.txt");
while (getline(myFile, line)) {
myFile >> temp.title;
myFile >> temp.artist;
myFile >> temp.genre;
songs.push_back(temp);
}
}
I then want to append to the file, using the following:
void SongList::AddSong(song tmp)
{
cout << "Enter the title, artist then genre of the song, each on a new line.\n";
cin >> tmp.title;
cin >> tmp.artist;
cin >> tmp.genre;
songs.push_back(tmp);
ofstream myFile("SongListFile.txt");
myFile.open("SongListFile.txt", ios::app);
myFile << tmp.title << " " << tmp.artist << " " << tmp.genre;
cout << tmp.title << " by " << tmp.artist << " is now a part of the song library! ";
}
Everything works fine, but the file will wipe and have nothing in it once I finish the program, even if I have tried to append to the file. To be clear, I need the previous contents, and new lines that I have added to be there every time I reopen the program.
std::ofstream myFile("SongListFile.txt"); opens the file and truncates. You should use std::ofstream myFile("SongListFile.txt", std::ios::app);
Otherwise you can declare the myFile object with std::ofstream myFile; and then open a file using it and the append option: myFile.open("SongListFile.txt", std::ios::app);
replace
ofstream myFile("SongListFile.txt");
myFile.open("SongListFile.txt", ios::app);
with
ofstream myFile("SongListFile.txt",ios::app);
or
ofstream myFile;
myFile.open("SongListFile.txt", ios::app);
what happens in your code is that the ofstream myFile("SongListFile.txt") opens the file with default mode ios::out and then the attempt to open the file with myFile.open("SongListFile.txt", ios::app); in the next line fails because the file is already opened by the previous line making the ios::app ineffective for the file and thus every time you open the file using ofstream, the file gets truncated.
Actually ofstream constructor has 3 parameters: (const char *_Filename, ios_base::openmode _Mode = ios_base::out, int _Prot = (int)ios_base::_Openprot).
So the call std::ofstream myFile("SongListFile.txt"); is equavalent to
std::ofstream myFile("SongListFile.txt", std::ios::out);
Remark: std::ios::out == ios_base::out.
Other possible values for the second argument are:
std::ios::app
std::ios::trunc
Deeper in CRT code this parameter is first translated according to this:
std::ios::out --> std::ios::out
std::ios::trunc --> std::ios::trunc | std::ios::out
std::ios::app --> std::ios::app | std::ios::out
And a bit more deeper it is translated into good old fopen modes according to this:
std::ios::out --> "w"
std::ios::trunc | std::ios::out --> "w"
std::ios::app | std::ios::out --> "a"
fopen modes description from MSDN:
"w" - Opens an empty file for writing. If the given file exists, its contents are destroyed.
"a" - Opens for writing at the end of the file (appending) without removing the end-of-file (EOF) marker before new data is written to the file. Creates the file if it does not exist.
TL;DR:
std::ofstream myFile("SongListFile.txt"); - reset the file content.
std::ofstream myFile("SongListFile.txt", std::ios::out); - reset the file content.
std::ofstream myFile("SongListFile.txt", std::ios::trunc); - reset the file content.
std::ofstream myFile("SongListFile.txt", std::ios::app); - don't reset the file content.
First 3 variants are equivalent (for std::ofstream!).

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

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

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);

Unable to print text from file

I'm trying to write a simple program that will print the contents of a text file one line at a time. However, whenever I run the program i just get a blank screen. I'm certain the file I am trying to read contains text over several lines. Any help as to why this isn't working would be super helpfull.
bool show() {
string line;
ifstream myfile;
myfile.open("tasks.txt", ios::app);
while (!myfile.eof()) {
getline (myfile, line);
cout << line << endl;
}
myfile.close();
return true;
}
The problem might be that you are using ios::app with ifstream (input stream), which makes no sense.
According to this,
ios::app: All output operations are performed at the end of the file, appending the content to the current content of the file. This flag can only be used in streams open for output-only operations.
Try this:
std::string line;
ifstream myfile ("tasks.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
std::cout << line << std::endl;
}
myfile.close();
}
Did you check return value of myfile.isopen()? Perhaps the file isn't there or you don't have read permission.
Oh yes, I missed that - the append flag. Should be ios::in