Resetting the End of file state of a ifstream object in C++ - c++

I was wondering if there was a way to reset the eof state in C++?

For a file, you can just seek to any position. For example, to rewind to the beginning:
std::ifstream infile("hello.txt");
while (infile.read(...)) { /*...*/ } // etc etc
infile.clear(); // clear fail and eof bits
infile.seekg(0, std::ios::beg); // back to the start!
If you already read past the end, you have to reset the error flags with clear() as #Jerry Coffin suggests.

Presumably you mean on an iostream. In this case, the stream's clear() should do the job.

I agree with the answer above, but ran into this same issue tonight. So I thought I would post some code that's a bit more tutorial and shows the stream position at each step of the process. I probably should have checked here...BEFORE...I spent an hour figuring this out on my own.
ifstream ifs("alpha.dat"); //open a file
if(!ifs) throw runtime_error("unable to open table file");
while(getline(ifs, line)){
//......///
}
//reset the stream for another pass
int pos = ifs.tellg();
cout<<"pos is: "<<pos<<endl; //pos is: -1 tellg() failed because the stream failed
ifs.clear();
pos = ifs.tellg();
cout<<"pos is: "<<pos<<endl; //pos is: 7742'ish (aka the end of the file)
ifs.seekg(0);
pos = ifs.tellg();
cout<<"pos is: "<<pos<<endl; //pos is: 0 and ready for action
//stream is ready for another pass
while(getline(ifs, line) { //...// }

Related

File handling not working with fstream after reaching eof?

On your suggestion i have changed the code as you suggested but still problems are there when ios::out is replaced with ios::ate nothing is written in the file(Writing does not work). Is there any way to check that if the next bit is eof rather than reading it and then checking it? as suggested by you.And sometimes when i do file handling it shows the position of file pointer to be -1 what could that mean???
Code:
int main ()
{
char p[80];
fstream file("text1.txt",ios::out|ios::in); //if ios::ate is added here it results into infinite loop
cout<<"Starting position of the file is "<<file.tellg()<<endl;
getch();
if(file.is_open())
cout<<"file is open\n";
else
cout<<"file is not open\n";
getch();
file.seekp(0);
while(file>>p)
{
cout<<p<<endl;
}
file.clear();
cout<<"\nThe current position of the file pointer is "<<file.tellg()<<endl;
file.seekp(0);
if(file.eof())
cout<<"\n the eof\n";
while(file>>p)
{
cout<<p<<endl;
}
file.close();
return 0;
}
Output:
Starting position of the file is 0
file is open
Hello
man
how
are
you
The current position of the file pointer is 21
Hello
man
how
are
you
With this kind of reading from file reaching end-of-file causes setting both eof and failbit. Failbit is setted because creating your read loop with file.eof() condition doesn't indicate that next read will be the end of the stream. It just states that we didn't reach eof yet, so with:
while(file.eof())
{
file >> p;
}
It's possible that last read will be eof only, and we'll work with uninitialised data. IF this happens no characters will be extracted inside p and both eof and fail flags will be set.
When working with c++98 need to reset failbit to false by using:
file.clear();
To avoid bad readings situation you should extract characters from file inside while condition: while(file >> p). I recommend this or this questions on stack overflow.
So proper C++98 code should look like this:
while(file >> p)
{
std::count << p << std::endl;
}
file.clear();
file.seekp(0);
while(file >> p)
{
std::count << p << std::endl;
}
file.close();
I tested it couple of times on Visual Studio 2013 and it worked everytime.
Considering ios::ate mode:
ios::out, ios::in are modifiers that states how do we open file in question. If you want to read something from file you need to use ios::out flag, and for writing you need to use ios::in.
On the other hand ios::ate just tells compiler to open file and immediately go to the end of file. So if you substitute ios::out with ios::ate writing would be impossible, and program will rise failflag on file << "Hello...";.
And if you just want to append data, but read from the beginning of file you should use ios::app instead, because it tells to seek eof before each write.

File Stream failing on read after seeking to end of file

I need to read the last 64kb from a large file, but after seeking to the end of the file, then back 64kb, all reads on the file fail.
Here's a snippet:
string filename = "test.txt";
ifstream::streampos pos; // used to keep track of position in file
ifstream fs;
fs.open(filename, ios::binary);
fs.seekg(0, ios::end);
pos = fs.tellg();
// ....
fs.seekg(-16, ios::cur);
char buff[16];
fs.read(buff, 16);
// ...
fs.close();
The problem is on fs.read() the eofbit, failbit, and badbit are set and the file stream becomes unusable. It is worth noting that the file I'm reading from is being continuously appended to. Also, sometimes this approach works and sometimes it doesn't, which makes debugging difficult.
Is there any reason why this would be happening?
Your problem is that you call tellg after seeking the end of file. tellg causes the pointer to advance invoking the eof state on the stream: Here is the issue:
fs.open(filename, ios::binary);
fs.seekg(0, ios::end);
pos = fs.tellg(); // <== causes eof on stream
Your next call to fs.seekg should clear the eof state, but it is probably better to call fs.clear() and check the return to insure it succeeds.

How to check if there isn't data in file to read

std::fstream fin("emptyFile", std::fstream::in);
std::cout << fin.eof() << std::endl;
This prints 0. So using eof function I can't check if file is empty. Or after reading some data I need to check if there is no more data in it.
There are two ways to check if you "can read something" from a file:
Try to read it, and if it fails, it wasn't OK... (e.g fin >> var;)
Check the size of the file, using fin.seekg(0, ios_base::end); followed by size_t len = fin.tellg(); (and then move back to the beginning with fin.seekg(0, ios_base::beg);)
However, if you are trying to read an integer from a text-file, the second method may not work - the file could be 2MB long, and still not contain a single integer value, because it's all spaces and newlines, etc.
Note that fin.eof() tells you if there has been an attempt to read BEYOND the end of the file.
eof() gives you the wrong result because eofbit is not set yet. If you read something you will pass the end of the file and eofbit will be set.
Avoid eof() and use the following:
std::streampos current = fin.tellg();
fin.seekg (0, fin.end);
bool empty = !fin.tellg(); // true if empty file
fin.seekg (current, fin.beg); //restore stream position

Can't read file more than once in c++

In my assignment i have a problem with reading a file. See the following code segment.
std::string data;
std::ifstream fileRead;
fileRead.open("a.txt");
while (fileRead >> data)
{
long a = fileRead.tellg();
fileRead.seekg (a+1, ios::beg);
std::string check;
//some code here
while (fileRead >> check)
{
//some code here
}
fileRead.seekg (a+1, ios::beg);
}
I have to check how many same words are in the file. My logic is, i read a word and keep it in data. Then i continue reading after that word using fileRead.seekg (a+1, ios::beg); Then i compare each of the words in the file.
After checking whole file i again put my fileobject to next word using this line fileRead.seekg (a+1, ios::beg); But this line is not working. I mean first while loop just work once. Someone please help me out here.
By the way, i am totally new in file operation. So my logic or concept may not be correct in that case tell me what is the right way to do this? But i need to know why first while loop ends just after reading one word?
When you read file as while(fileRead >> data), the a failure flag is set for the stream object, before exiting the loop. In fact, it is set that is why it exits the loop. You need to clear this failure flagas:
fileRead.clear(); //clear the failure flag
fileRead.seekg (0, ios::beg);
//now read

How to go back to the beginning of a file after reaching .eof() in C++?

I just tried this, but don't work, maybe because I'm reading character by character?
char character;
while (!file.eof()) {
character = file.get();
cout << character;
}
Did you try the accepted answer? The call to clear is the key.
If your input is a stream (data piped in from another program) then you will not be able to seek.
OK, it works. The trick is call
file.clear();
file.seekg(0, ios::beg);
just after the iteration. Sorry :(