I have seen cout.rdbuf() in for example here. This implies, the stream cout have a stream buffer associated with it, which is non empty before we flush it.
But, how can I ever peek into cout's stream buffer for cout before it's flushed?
Ie
cout << "I want to read this before this get flushed";
cout.UnknownFunction(); //this would save the buffer into a string variable
cout << flush;
But in current form of the code, everything will be flushed onto the screen after the first line..
So, what kind of construct allows me to peek inside the cout buffer?
PS. im running VC++ 2010 on windows7
I think that this doesn't flush after the first line, but I'm absolutely NOT sure.
I experienced that endl flushes, but the others don't, it's possible that too much character automatically flushes, but I don't know.
I created (accidentally) a program like this (in short):
cout << "x";
while (true) {}
The program ran this, and the output would be debug, but it haven't written anything for me, so I thought the program doesn't get there...
Following link is closely related to this topic
C++ buffered stream IO
(But I'm still not sure how/when to get cout.rdbuf() onto a string.)
Related
First of all, this question is based on my last question here: Reading Console Buffer / Output C++
I have a compiled executable binary file. It has some outputs, what I would like to redirect it to an other program, that handles the lines. I successfully found where the output is sent, and I modified it to STDOUT. The problem is that, when I use it like:
./jampDed.exe | stdout.exe
then the output is not synced. I got the content after every 1000-2000 bytes.
stdout.cpp
#include <iostream>
int main() {
std::string s;
while (std::getline(std::cin, s, '\n')) {
std::cout << s << std::endl;
}
return 0;
}
I also created a picture about assembly modification, where Kernel32.WriteFile function was used by default.
So the question is that, how can I make it synced? How to get every line as soon as it happens on the dedicated server?
Somewhere in the executable where it establishes stdout is an option bit for unbuffered output. Just set (or clear) that bit. Then every call to write is transferred without delay. This adds significant execution time and i/o system effort to that program but is probably okay for this.
The program which processes that output (as input) should buffer full lines because the program is unlikely to do full line output itself.
Why don't you try:
std::cout << s << std::endl << std::flush;
^^^^^^^^^^
IS there a way to delete or rewrite a symbol on the console window? Something like System("cls") but for a single symbol.
Thanks
First of all, you are usually working with standard output stream with C++, not with console itself. And you are not able to navigate through it.
From the other hand, you can use specific platform dependent console libraries (like ncurses or Windows console functions) to handle console.
However, if you are actually printing to the console you can use some symbols to control the last line:
You can send '\b' (Backspace) to move one character left on the current line.
You can send '\r' to move to the beginning of the current line.
Don't forget also, that stdout usually line-buffered and you may have to flush by hands.
int main()
{
std::cout << "Hi\r" << std::flush;
Sleep(1000); //or whatever to delay
std::cout << "hellq" << std::flush; // flushing by hands
Sleep(1000);
std::cout << "\bo";
}
I encountered a strange problem earlier. I was working at insertion in B-trees and I wrote a simple display function. I ran it and it didn't show anything in the console even though I inserted some values.
I entered in the debug mode, I followed the flow of the program and the debugger showed me that the tree had values in it. Then I wanted to display only the first node's elements and I had the same problem: an empty console.
I asked my teacher what would be the mistake and he told me to put an endl after cout, like this:
cout << node->keys[i] << endl;
It worked!
He told me then that probably I addressed a NULL pointer in my program and Eclipse doesn't say anything about that but nothing about how endl could help.
Does anybody know what could be the problem and how that endl solves it? I'm very very confused.
I didn't understand what flushing the buffer has to do with my display function.
I'm a bit late to answer and how to flush has been explained by the other answers already so I wanna answer your comment on Johnsy's answer at least.
First the reason that output is buffered is that writing the data to some output stream and not in the memory is usually a really slow operation (this ofc depends if you wanna write to a file on a ssd or hdd or just to the display but they all are way slower than the ram).
So c++ writes it to an internal buffer first and only actually writes to the output when the buffer is full or you flush the stream. It does so to avoid the slow operation of writing on most output streams.
So now why do you need to flush the buffer before it gets displayed...
Like already said it only actually writes it out for you to see when the buffer is full or it gets explicitly flushed. Now when the program ends normally all streams get flushed automatically so what happens prolly is a crash of the Program (a crash won't flush the buffer) so your program quits w/o it ever displaying.
Since your program displays everything correctly when you add the endl I guess you're trying to output a node with a nullptrat the very end and crash just before returning from main. You could easily test that by adding std::cout << "end of the program" << std::endl; just before your returnin main and testing if it gets displayed.
std::endl flushes output stream....
cout is buffered, output will not be displayed immediately, they will be buffered, until the buffer overflows, then all buffered data will be displayed. If you want display the ouput sooner, flush it.
Inserts a endline character into the output sequence os and flushes it
as if by calling os.put(os.widen('\n')) followed by os.flush().[1]
You can use std::cout.flush(); too.
std::endl inserts a endline character into the output sequence (os, in your case cout) and flushes it as if by calling os.put(os.widen('\n')) followed by os.flush().
std::cout controls output to a stream buffer of implementation-defined type (derived from std::streambuf), associated with the standard C output stream stdout. This output is buffered (unlike std::cerr)
Before you put endl into your source code, your buffer was not being flushed and the output was not appearing on your screen.
std::endl not only appends a newline character to the output stream, but also causes it to be flushed. I'm not quite sure how large the buffer on std::cout is, but it is possible that you're not seeing anything because the buffer is not full and thus does not get flushed. You could try to call cout.flush(); after appending your data (without appending std::endl) and see if that solves the problem.
As M M has mentioned in his answer as have others above, the std::endl flushes output stream. What it means is to display or put the results/output to the standard output source immediately/real time.
Using '\n' instead of std::endl will also result in similar output but may not be displayed immediately if some operation is still going on.
The common down side of std::endl is considered to be degradation of performance, though it may not be of significance if the output is streamed to a display instead of a file - where the '\n' is the preferred method.
Hope this helps.
I have the following code:
ofstream mOutFile.open(logPath, ios_base::app);
string lBuilder;
lBuilder.append("========================================================\n");
lBuilder.append("Date: ");
lBuilder.append(asctime(timeinfo));
lBuilder.append("\n");
lBuilder.append("Log Message:\n");
lBuilder.append(toLog);
lBuilder.append("\n");
lBuilder.append("========================================================\n\n");
int lSize = lBuilder.size();
char* lBuffer = new char[lSize];
int index = 0;
for each (char c in lBuilder)
lBuffer[index++] = c;
mOutFile.write(lBuffer, lSize);
mOutFile.flush();
Unfortunately, until I close the app (I assume that closing the ofstream would work as well) the output does not get written to the text file. I know I could probably close and reopen the stream and everything will "just work" but that seems like a silly and incorrect solution. What am I doing wrong here?
I have also tried the following variations based on other questions I have found here, but these solutions did not work:
mOutputFile << flush;
mOutputFile << endl;
Thanks in advance for any assistance on this.
edit Everything in this code is working visual c++, it builds and works fine except the file is not written to until the stream is closed, even if I force a flush. Also, I switched from using the << operator to the char * and .write () to see if anything behaved differently.
std::ofstream file(logPath, ios_base::app);
file << "========================================================\n"
<< "Date: " << asctime(timeinfo)
<< "\nLog Message:\n" << toLog
<< "\n========================================================\n\n"
<< std::flush;
//if you want to force it write to the file it will also flush when the the file object is destroyed
//file will close itself
This is not only easier to read but it will probably also be faster than your method + it is a more standard appraoch
I ended up just "making it work" by closing and reopening the stream after the write operation.
mOutputFile << "all of my text" << endl;
mOutputFile.close();
mOutputFile.open(mLogPath);
EDIT After trying out forcing the flush on a few other systems, it looks like something just isn't performing correctly on my development machine. Not good news but at least the above solution seems to work when programmatically flushing the ofstream fails. I am not sure of the implications of the above code though, so if anyone wants to chime in if there are implications of closing and reopening the stream like this.
You can perform the following steps to validate some assumptions:
1.) After flush(), the changes to the file should be visible to your application. Open the file as std::fstream instead of std::ofstream. After flushing, reset the file pointer to the beginning and read the contents of the file. Your newly written record should be there. If not, you probably have a memory corruption somewhere in your code.
2.) Open the same file in an std::ifstream after your call to flush(). Then read the contents of the file. Your newly written record should be there. If not, then there's probably another process interfering with your file.
If both works, then you may want to read up on "file locking" and "inter-process syncronization". The OS can (theoretically) take as much time as it wants to make file changes visible to other processes.
I've got a program that is tailing a growing file.
I'm trying to avoid grabbing a partial line from the file (e.g. reading before the line is completely written by the other process.) I know it's happening in my code, so I'm trying to catch it specifically.
Is there a sane way to do this?
Here's what I'm trying:
if (getline (stream, logbuffer))
{
if (stream.eof())
{
cout << "Partial line found!" << endl;
return false;
}
return true;
}
return false;
However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code. std::getline strips off newlines, so I can't check the buffer for a trailing newline. My log message (above) is NEVER tripping.
Is there some other way of trying to check what I want to detect? Is there a way to know if the last line I read hit EOF without finding a EOL character?
Thanks.
This will never be true:
if (getline (stream, logbuffer))
{
if (stream.eof())
{
/// will never get here
If getline() worked, the stream cannot be in an eof state. The eof() and related state tests only work on the results of a previous read operation such as getline()- they do not predict what the next read will do.
As far as I know, there is no way of doing what you want. However, if the other process writes a line at a time, the problems you say you are experiencing should be very rare (non -existent in my experience), depending to some extent on the OS you are are using. I suspect the problem lies elsewhere, probably in your code. Tailing a file is a very common thing to do, and one does not normally need to resort to special code to do it.
However, should you find you do need to read partial lines, the basic algorithm is as follows:
forever do
wait for file change
read all possible input using read or readsome (not getline)
chop input into lines and possible partial line
process as required
end
An istream object such as std::cin has a get function that stops reading when it gets to a newline without extracting it from the stream. You could then peek() or get() it to see if indeed it is a newline. The catch is that you have to know the maximum length of a line coming from the other application. Example (untested) code follows below:
char buf[81]; // assumes an 80-char line length + null char
memset(buf, 0, 81);
if (cin.get(buf, 81))
{
if (cin.peek() == EOF) // You ran out of data before hitting end of line
{
cout << "Partial line found!\n";
}
}
I have to take issue with one statement you made here:
However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code.
It seems like from what you said it would be extremely easy to replicate your problem, if it is what you said. You can easily create a text file in some text editor - just make sure that the last like ends in an EOF instead of going on to a new line. Then point your program at that file and see what results.
Even if the other program isn't done writing the file, in the file that's where the line ends, so there's no way to tell the difference other than waiting to see if the other program writes something new.
edit: If you just want to tell if the line ends in a newline or not, you could write your own getline function that reads until it hits a newline but doesn't strip it.