Returning to beginning of file after getline - c++

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)

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)

How Can I Detect That a Binary File Has Been Completely Consumed?

If I do this:
ofstream ouput("foo.txt");
output << 13;
output.close();
ifstream input("foo.txt");
int dummy;
input >> dummy;
cout << input.good() << endl;
I'll get the result: "0"
However if I do this:
ofstream ouput("foo.txt", ios_base::binary);
auto dummy = 13;
output.write(reinterpret_cast<const char*>(&dummy), sizeof(dummy));
output.close();
ifstream input("foo.txt", ios_base::binary);
input.read(reinterpret_cast<char*>(&dummy), sizeof(dummy));
cout << input.good() << endl;
I'll get the result: "1"
This is frustrating to me. Do I have to resort to inspecting the ifstream's buffer to determine whether it has been entirely consumed?
Regarding
How Can I Detect That a Binary File Has Been Completely Consumed?
A slightly inefficient but easy to understand way is to measure the size of the file:
ifstream input("foo.txt", ios_base::binary);
input.seekg(0, ios_base::end); // go to end of the file
auto filesize = input.tellg(); // current position is the size of the file
input.seekg(0, ios_base::beg); // go back to the beginning of the file
Then check current position whenever you want:
if (input.tellg() == filesize)
cout << "The file was consumed";
else
cout << "Some stuff left in the file";
This way has some disadvantages:
Not efficient - goes back and forth in the file
Doesn't work with special files (e.g. pipes)
Doesn't work if the file is changed (e.g. you open your file in read-write mode)
Only works for binary files (seems your case, so OK), not text files
So better just use the regular way people do it, that is, try to read and bail if it fails:
if (input.read(reinterpret_cast<char*>(&dummy), sizeof(dummy)))
cout << "I have read the stuff, will work on it now";
else
cout << "No stuff in file";
Or (in a loop)
while (input.read(reinterpret_cast<char*>(&dummy), sizeof(dummy)))
{
cout << "Working on your stuff now...";
}
You are doing totally different things.
The operator>> is greedy and will read as much as possible into dummy. It so happens that while doing so, it runs into the end of file. That sets the input.eof(), and the stream is no longer good(). As it did find some digits before the end, the operation is still successful.
In the second read, you ask for a specific number of bytes (4 most likely) and the read is successful. So the stream is still good().
The stream interface doesn't predict the outcome of any future I/O, because in the general case it cannot know. If you use cin instead of input there might now be more to read, if the user continued typing.
Specifically, the eof() state doesn't appear until someone tries to read past end-of-file.
For text streams, as you have written only the integer value and not even a space not an end of line, at read time, the library must try to read one character passed the 1 and 3 and hits the end of file. So the good bit is false and the eof is true.
For binary streams, you have written 4 bytes (sizeof(int)) assuming ints are 32 bits large, and you read 4 bytes. Fine. No problem has still occured and the good bit is true and eof false. Only next read will hit the end of file.
But beware. In text example, if you open the text file in a editor and simply save it without changing anything, chances are that the editor automacally adds an end of line. In that case, the read will stop on the end of line and as for the binary case the good bit will be true and eof false. Same is you write with output << 13 << std::endl;
All that means that you must never assume that a read is not the last element of a file when good it true and eof is false, because the end of file may be hit only on next read even if nothing is returned then.
TL/DR: the only foolproof way to know that there is nothing left in a file is when you are no longer able to read something from it.
You do not need to resort to inspecting the buffer. You can determine if the whole file has been consumed: cout << (input.peek() != char_traits<char>::eof()) << endl This uses: peek, which:
Reads the next character from the input stream without extracting it
good in the case of the example is:
Returning false after the last extraction operation, which occurs because the int extraction operator has to read until it finds a character that is not a digit. In this case that's the EOF character, and when that character is read even as a delimiter the stream's eofbit is set, causing good to fail
Returning true after calling read, because read extracts exactly sizeof(int)-bytes so even if the EOF character is the next character it is not read, leaving the stream's eofbit unset and good passing
peek can be used after either of these and will correctly return char_traits<char>::eof() in both cases. Effectively this is inspecting the buffer for you, but with one vital distinction for binary files: If you were to inspect a binary file yourself you'd find that it may contain the EOF character. (On most systems that's defined as 0xFF, 4 of which are in the binary representation of -1.) If you are inspecting the buffer's next char you won't know whether that's actually the end of the file or not.
peek doesn't just return a char though, it returns an int_type. If peek returns 0x000000FF then you're looking at an EOF character, but not the end of file. If peek returns char_traits<char>::eof() (typically 0xFFFFFFFF) then you're looking at the end of the file.

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

Read file from position (to position)

File-Stream/ifstreamreadbufferandseekfileposition.htm">http://www.java2s.com/Tutorial/Cpp/0240_File-Stream/ifstreamreadbufferandseekfileposition.htm
this page is able to print content of a file twice using
file.seekg(0);
So I assume that seekg(0) puts the "cursor" (in java) to the beginning of the file, and this web site: http://www.cplusplus.com/doc/tutorial/files/ confirms me.
But when I do this to a file that contains (0\n0\n0\n):
while(getline(file,line)) {
CCLOG(line.c_str());
CCLOG("%d",(int)file.tellg());
}
file.seekg(0);
CCLOG("%d",(int)file.tellg());
while(getline(file,line)) {
CCLOG(line.c_str());
}
(I'm doing this in cocos2dx 2.2.2 by the way)
it prints:
0
2
0
4
0
6
-1
I don't know what I'm doing wrong. Please help
I'm not 100% sure what you're asking here (and what it has to do with Java), but if you're asking why resetting the file cursor to the beginning of the file does not work, then here's my answer:
Make sure you reset the error flags of file before you call seekg. So instead of just
file.seekg(0);
write
file.clear();
file.seekg(0);
That will successfully reset the file cursor to the beginning of the file. The reason for this is, that once you reach the end of the file, the EOF (end-of-file) flag will be set and seekg does not reset it.
The reason for the behaviour you are seeing is that, once you read to the end of the file, the eof() state flag will be set. Any attempt to read or position the file after that will trigger an error. The error resulting in a return code of ERROR, which is -1.
You can reset the state flags (all of them) using clear(). So the code should read
file.clear();
file.seekg(0);

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

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.