Can't write to file in a loop containing sleep() - c++

The essence of my problem is that I can't write to a file in a loop with sleep(). If I have the following code:
ofstream file
file.open("file.name");
for(;;) {
file << "HELLO\n";
}
This code works perfectly and prints HELLO repeatedly into "file.name". However, I want to do something like this (I'm recording data from a real-time application):
for(;;) {
file << "HELLO\n";
sleep(1);
}
This doesn't seem to print anything into my file. Any ideas?

You need to flush the output. The output stream is buffering your data into memory but not writing it out to disk. You should either use std::endl (which prints a newline and flushes) instead of the string literal '\n', or explicitly flush the stream with std::flush:
for(;;) {
file << "HELLO" << endl;
}
// or
for(;;) {
file << "HELLO\n" << flush;
}

The magic word you are looking for is "flush".
c++ std::ofstream flush() but not close()
before the sleep, flush the file so that it isn't pending in a buffer waiting for there to be enough of a change to bother writing out.

It's probably just a buffering issue. Because you are now writing much slower, the output buffer wont fill up so fast so you may not 'see' the written data. Try adding a flush() before the sleep.
file.flush()

Related

unable to read and write using same fstream object in c++

I'm trying to use same fstream object for first write the file and after that read the file.
when I'm using below code then the codes of writing the file is working but I'm getting junk output instead of texts which written in the file.
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main() {
fstream file;
file.open("test.txt",ios::in|ios::out| ios::trunc);
if (!file) {
cout << "Error";
}
else {
cout << "success";
file <<"\n\n1st Line\n 2nd line \n 3rd line\n";
string filecontent;
while (file.good()) {
getline(file, filecontent);
cout << filecontent << endl;
}
}
return 0;
}
Output
This code has two separate problems. The first (which others have already pointed out to at least some degree) is that your loop isn't detecting the end of the file correctly. In fact, almost any time you use while (!file.eof()) or while (file.good()), it's going to be a mistake--it won't detect end of file at the right time, so (for example) when you reach the end of the file, you won't detect it at the right time, and you'll see the last item in the file appear to be read twice before the loop exits.
In addition to that, however, you have a problem in that you're writing to the file, then immediately trying to read. That's simply not allowed--you want to do a seek any time you switch between reading and writing.
In this case, you have a bit of a further problem. Since you've just written data into the file, your file's current position is at the end of the file. So even if you could just start reading without seeking, you'd start reading from the end of the file. That, of course, would immediately fail.
So you also really need to seek back to the beginning of the file to be able to read it back in.
So, the big changes here are adding a line like: file.seekg(0); after you finish writing, but before you start to try to read that data back in, and then changing your reading loop to something like:
while (getline(file, filecontent)) {
cout << filecontent << endl;
}
One last point: although it's not going to make a big difference in this case, I'd advise using "\n" instead of std::endl. std::endl writes a new-line and flushes the file buffer. When you're writing to the screen it won't make any real difference, but when writing to a normal file flushing the buffer unnecessarily can and will slow your code substantially (10x slower is pretty common).

Why is stream::ignore not working as intended?

As far as I know, stream.ignore(n, 'n') should ignore an (n) amount of characters or if ā€˜\nā€™ is reached, and skip over to the next line, however, when I run the next code:
// include...
void insertInfo(int info) {
std::fstream stream("infoFile.txt"); // Open the file
while (!stream.eof()) {
std::string a{};
// getline(stream, a); <--- Tried this, didn't work either
stream.ignore(99, '\n');
} // Skip to the last line without any number, in theory
std::cout << info << std::endl; // Check if the output it's correct (Which is)
stream << info; // Insert the info
stream.close(); // Close the file
}
void main() //Main
{
std::cout << "Enter your name, followed by the info you want to add to infoFile:" << std::endl;
std::string info, temp = "";
std::getline(std::cin, temp); // Get the info input
std::stringstream sstream;
sstream << temp;
sstream >> temp >> info; // Remove the name keeping only the info
temp = ""; // ^
std::string::size_type sz;
insertInfo(stoi(info, &sz)); // Convert info string into an integer and insert it in infoFile
}
The console prints out the "info" correct value, however, when I check info.txt, in which I previously wrote a '0' on, you don't see any change.
I tried removing the "ignore" function and it overwrites the 0, which is exactly what I was trying to prevent.
I also tried using "getline" function but the same thing happens.
What is the error here?
Problem
Cannot write to file.
Why
void insertInfo(int info) {
std::fstream stream("infoFile.txt"); // Open the file
Opens file with default permissions, which includes reading. The C++ Standard says I should expect "r+" behaviour and the C Standard says a file opened with "r+" behaviour must exist in order to be read (Someone please add a link if you have one). You cannot create a new file. This is problem 1. The Asker has dealt with this problem by providing a file.
Note: take care when working with files via relative paths. The program's working directory may not be where you think it is. This is problem 1a. It appears that the Asker has this taken care of for the moment.
while (!stream.eof()) {
Common bug. For more details see Why is iostream::eof inside a loop condition considered wrong? In this case since all you're looking for is the end of the file, the fact that the file hasn't been opened at all or has encountered any read errors is missed. Since a file in an error state can never reach the end of the file this quickly becomes an infinite loop. This is problem 2.
std::string a{};
// getline(stream, a); <--- Tryied this, didn't work neither
stream.ignore(99, '\n');
Always test IO transactions for success. This call can fail unchecked.
} // Skip to the last line without any number, in theory
Assuming nothing has gone wrong, and since we're not checking the error state assuming's all we can do, the file has reached the end and is now in the EOF error state. We can't read from or write to the stream until we clear this error. This is problem number 3 and likely the problem the Asker is struggling with.
std::cout << info << std::endl; // Check if the output it's correct (Wich is)
stream << info; // Insert the info
This can fail unchecked.
stream.close(); // Close the file
This is not necessary. The file will be closed when it goes out of scope.
}
Solution
void insertInfo(int info) {
std::fstream stream("infoFile.txt"); // Open the file
while (!stream.eof()) {
stream.ignore(99, '\n');
} // Skip to the last line without any number, in theory
std::cout << info << std::endl; // Check if the output it's correct (Wich is)
stream.clear(); // Added a call to clear the error flags.
stream << info; // Insert the info
stream.close(); // Close the file
}
Now we can write to the file. But let's improve this shall we?
void insertInfo(int info) {
std::fstream stream("infoFile.txt");
while (stream.ignore(99, '\n')) // moved ignore here. now we ignore, then test the result
{
}
stream.clear();
stream << info << '\n'; // added a line ending. Without some delimiter the file
// turns into one big number
}
Note that this isn't exactly kosher. If any ignore fails for any reason, we bail out and possibly write over data because the code blindly clears and writes. I'm not spending much time here trying to patch this up because we can get really, really simple and solve the problem of creating a non-existent file at the same time.
void insertInfo(int info) {
std::fstream stream("infoFile.txt", std::ios::app);
stream << info << '\n';
}
Two lines and pretty much done. With app we append to the file. We do not need to find the end of the file, the stream automatically points at it. If the file does not exist, it is created.
Next improvement: Let people know if the write failed.
bool insertInfo(int info) {
std::fstream stream("infoFile.txt", std::ios::app);
return static_cast<bool>(stream << info << '\n');
}
If the file was not written for any reason, the function returns false and the caller can figure out what to do. The only thing left is to tighten up the stream. Since all we do is write to ti we don't need the permissiveness of a fstream. Always start with the most restrictive and move to the least. This helps prevent some potential errors by making them impossible.
bool insertInfo(int info) {
std::ofstream stream("infoFile.txt", std::ios::app);
return static_cast<bool>(stream << info << '\n');
}
Now we use an ofstream and eliminate all the extra overhead and risk brought in by the ability to read the stream when we don't read the stream.

Printf Fprintf outputorder

I don't get why "cout" outputs after the file is written, it makes no sense to me... How would I do it correctly? I tried with sleep between the two, but it's still not reversing the order like I want to.
cout << "Writing to file";
fp = fopen("plume_visualisation.txt","w");
for(int i=0;i<grid;i++)
for(int j=0;j<grid;j++)
for(int k=0;k<grid;k++)
fprintf(fp,"%f\t%f\t%f\t%f\n",x[i],y[j],z[k],suv[i][j][k]);
fclose(fp);
C++ writes to the output stream, stored in a buffer. You need to flush the buffer to write it to the console. Remember how you probably learned to write a line to the console?
std::cout << "This is a message" << std::endl;
What std::endl does is place a newline character at the end of the message, and flush the buffer. Based on your code, I'm guessing you thought "Hey, I can just leave off endl and it won't write a new line." This is a good way to think...but you probably didn't realize that endl also flushes the buffer. This is what you want:
std::cout << "Writing to file" << std::flush;
Also notice how I prefixed cout and flush with "std." Using "using namespace standard" is bad practice that you should avoid.
On a related note, you're already using C++. Instead of doing file IO the old C way of fprintf, instead set up a file stream. It works pretty much the same way that console IO does. Here's a great guide on how to do what you're doing in a more idiomatic fashion: http://www.cplusplus.com/doc/tutorial/files/

ifstream pipe and multiple (sequential) writers

I'm reading from a named pipe on Linux using std::ifstream. If the writing end of the file is closed, I can not continue reading from the pipe through the stream. For some reason I have to clear(), close() and open() the stream again to continue reading. Is this expected? How can I avoid the close() open() on a pipe when writers close() and open() the pipe at will?
Background: I believe the close() open() I have to do is causing the writer to sometimes receive SIGPIPE which I would like to avoid.
More details - I am using this code to read a stream
// read single line
stream_("/tmp/delme", std::ios::in|std::ios::binary);
std::getline(stream_, output_filename_);
std::cout << "got filename: " << output_filename_ << std::endl;
#if 0
// this fixes the problem
stream_.clear();
stream_.close();
stream_.open("/tmp/delme", std::ios::in|std::ios::binary);
// now the read blocks until data is available
#endif
// read more binary data
const int hsize = 4096+4;
std::array<char, hsize> b;
stream_.read(&b[0], hsize);
std::string tmp(std::begin(b), std::begin(b)+hsize);
std::cout << "got header: " << tmp << std::endl;
/tmp/delme is my pipe. I do echo "foo" > /tmp/delme and I get the foo in output_filename_ but the stream does not block there, (it should, there is no more data), it proceeds to read garbage. If I enable the code within the ifdef it works. Why?
Thanks,
Sebastian
Since you use std::getLine(), maybe you need to use an extra "\n" to signal the end of a line:
echo -e "foo\n" > /tmp/delme
instead of just
echo "foo" > /tmp/delme
This should at least get rid of the garbage reading.

What does flushing the buffer mean?

I am learning C++ and I found something that I can't understand:
Output buffers can be explicitly flushed to force the buffer to be
written. By default, reading cin flushes cout; cout is also flushed
when the program ends normally.
So flushing the buffer (for example an output buffer): does this clear the buffer by deleting everything in it or does it clear the buffer by outputting everything in it? Or does flushing the buffer mean something completely different?
Consider writing to a file. This is an expensive operation. If in your code you write one byte at a time, then each write of a byte is going to be very costly. So a common way to improve performance is to store the data that you are writing in a temporary buffer. Only when there is a lot of data is the buffer written to the file. By postponing the writes, and writing a large block in one go, performance is improved.
With this in mind, flushing the buffer is the act of transferring the data from the buffer to the file.
Does this clear the buffer by deleting everything in it or does it clear the buffer by outputting everything in it?
The latter.
You've quoted the answer:
Output buffers can be explicitly flushed to force the buffer to be written.
That is, you may need to "flush" the output to cause it to be written to the underlying stream (which may be a file, or in the examples listed, a terminal).
Generally, stdout/cout is line-buffered: the output doesn't get sent to the OS until you write a newline or explicitly flush the buffer. The advantage is that something like std::cout << "Mouse moved (" << p.x << ", " << p.y << ")" << endl causes only one write to the underlying "file" instead of six, which is much better for performance. The disadvantage is that a code like:
for (int i = 0; i < 5; i++) {
std::cout << ".";
sleep(1); // or something similar
}
std::cout << "\n";
will output ..... at once (for exact sleep implementation, see this question). In such cases, you will want an additional << std::flush to ensure that the output gets displayed.
Reading cin flushes cout so you don't need an explicit flush to do this:
std::string colour;
std::cout << "Enter your favourite colour: ";
std::cin >> colour;
Clear the buffer by outputting everything.