How to detect end-of-file when using getline? - c++

while(getline(fileIn,line))
{
fileOut <<line<<endl;
}
while(getline(fileIn,line))
{
if(fileIn.eof())
break;
fileOut <<line<<endl;
}
I have tried both these pieces of code and the second one also reads past end-of-file and does not break. Can anyone tell me why?
I am just reading from a file and writing the lines out.

The getline function returns a reference to the stream you're reading. It evaluates to false if you try to read past EOF. The stream is still in a good state when you read the last line of the file. So you'll never reach the if-test in your second block of code.

Is that a comma between "fileIn" and "eof()"??? (second example)
One thing I like to do, is enable exceptions on my fstreams. YMMV:
ifstream file;
file.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);

The first code is correct and it certainly does end the loop after no data is left in the file.

Related

C++ while(file input stream) loop executes only once in the superior while loop [duplicate]

So i've read all the lines from a file thusly
while (getline(ifile,line))
{
// logic
}
Where ifile is an ifstream and line is a string
My problem is I now want to use getline over again, and seem to be unable to return to the beginning of the file, as running
cout << getline(ifile,line);
Will return 0
I've attempted to use:
ifile.seekg (0, ios::beg);
To no avail, it seems to have no effect. How do I go back to the start of the file?
Since you have reached (and attempted to read past) the end of the file, the eof and fail flags will be set. You need to clear them using ifile.clear – then try seeking:
ifile.clear();
ifile.seekg(0);
This is because the eof flag has been set on the stream - due to you reaching the end of the file. so you have to clear this as an additional step.
Eg
ifile.clear();
ifile.seekg (0, ios::beg);
FYI: In my case, the order DID matter, thus
clear
seek
otherwise the next getline operation failed (MSVC v120)

Reading a text file from the first line multiple times (C++)

I'm using "getline" to read some lines in a text file. It works as it should, but I'm calling the method multiple times.
while(getline(file, line))
{
//Do something
}
//More code in between
while(getline(file, line))
{
//Do something else
}
The problem is that when I call "getline" the second time it starts reading from where it previously finished (e.g. If the first while loop ends at the second line then the next loop starts at the third line). How can I ensure that my program reads the file from the first line every time?
If you need that same first line multiple times I think you should reconsider your strategy.
Just read the line once.
Save it in a variable (or just keep it in the variable "line" you already have).
Close the file.
You would avoid a lot of not necessary I/O operations...
Nonetheless as other people suggested if by any reason you want to procede with this approach you need to insert:
myinputstream.clear(); //clear the buffer
myinputstream.seekg(0, ios::beg); //reset the reading position to beginning
between each attempt to read the same file.
And do not forget to close it eventually.
myinputstream.close();
There's a seekg() function that should help
http://www.cplusplus.com/reference/istream/istream/seekg/
iostream::seekg (0, iostream::beg);
will move you at the beggining of the stream

Difference between while(!file.eof()) and while(file >> variable)

First things first - I've got a text file in which there are binary numbers, one number for each row. I'm trying to read them and sum them up in a C++ program. I've written a function which transforms them to decimal and adds them after that and I know for sure that function's ok. And here's my problem - for these two different ways of reading a text file, I get different results (and only one of these results is right) [my function is decimal()]:
ifstream file;
file.open("sample.txt");
int sum = 0;
string BinaryNumber;
while (!file.eof()){
file >> BinaryNumber;
sum+=decimal(BinaryNumber);
}
and that way my sum is too large, but by a small quantity.
ifstream file;
file.open("sample.txt");
int sum = 0;
string BinaryNumber;
while (file >> BinaryNumber){
sum+=decimal(BinaryNumber);
}
and this way gives me the the right sum. After some testing I came to a conclusion that the while loop with eof() is making one more iteration than the other while loop. So my question is - what is the difference between those two ways of reading from a text file? Why the first while loop gives me the wrong result and what may be this extra iteration that it's doing?
The difference is that >> reads the data first, and then tells you whether it has been a success or not, while file.eof() does the check prior to the reading. That is why you get an extra read with the file.eof() approach, and that read is invalid.
You can modify the file.eof() code to make it work by moving the check to a place after the read, like this:
// This code has a problem, too!
while (true) { // We do not know if it's EOF until we try to read
file >> BinaryNumber; // Try reading first
if (file.eof()) { // Now it's OK to check for EOF
break; // We're at the end of file - exit the loop
}
sum+=decimal(BinaryNumber);
}
However, this code would break if there is no delimiter following the last data entry. So your second approach (i.e. checking the result of >>) is the correct one.
EDIT: This post was edited in response to this comment.
When using file.eof() to test the input, the last input probably fails and the value stays unchanged and is, thus, processed twice: when reading a string, the stream first skips leading whitespace and then reads characters until it finds a space. Assuming the last value is followed by a newline, the stream hasn't touched EOF, yet, i.e., file.eof() isn't true but reading a string fails because there are no non-whitespace characters.
When using file >> value the operation is executed and checked for success: always use this approach! The use of eof() is only to determine whether the failure to read was due to EOF being hit or something else.

Returning to beginning of file after getline

So i've read all the lines from a file thusly
while (getline(ifile,line))
{
// logic
}
Where ifile is an ifstream and line is a string
My problem is I now want to use getline over again, and seem to be unable to return to the beginning of the file, as running
cout << getline(ifile,line);
Will return 0
I've attempted to use:
ifile.seekg (0, ios::beg);
To no avail, it seems to have no effect. How do I go back to the start of the file?
Since you have reached (and attempted to read past) the end of the file, the eof and fail flags will be set. You need to clear them using ifile.clear – then try seeking:
ifile.clear();
ifile.seekg(0);
This is because the eof flag has been set on the stream - due to you reaching the end of the file. so you have to clear this as an additional step.
Eg
ifile.clear();
ifile.seekg (0, ios::beg);
FYI: In my case, the order DID matter, thus
clear
seek
otherwise the next getline operation failed (MSVC v120)

std::getline and eol vs eof

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.