问题
I am creating a program (In C++) that takes an ASCII file and reads a few values from each line until it reaches the end of the file. I am using ifstream
to read the file, and I have never had problems with it stopping when I use the ifstream.eof()
method. This time, however, even though it found the eof character in my test case, when I analyzed my other files, it is infinite looping because it never finds the eof character. Is this a coding issue, or an issue with my files?
string line = "";
unsigned long pos = 0;
ifstream curfile(input.c_str());
getline(curfile, line);
int linenumber = 0;
cout<<"About to try to read the file"<<endl;
if (!curfile.good())
cout<<"Bad file read"<<endl;
while (!curfile.eof())
{
cout<<"Getting line "<<linenumber<<endl;
linenumber++;
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
pos = line.find_first_of(' ');
current.push_back(atof(line.substr(0, pos).c_str()));
for (int i = 0; i<4; i++)
{
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
}
pos = line.find_first_of(' ');
dx.push_back(atof(line.substr(0, pos).c_str()));
pos = line.find_first_of(' ');
line = line.substr(pos+1, line.size()-1);
pos = line.find_first_of(' ');
dy.push_back(atof(line.substr(0, pos).c_str()));
getline(curfile, line);
}
EDIT: When I first run the loop, currentfile.good() returns false...what am I doing that causes it to return that?
回答1:
First thing is first, you shouldn't check like that. eof()
doesn't return true
until after a failed read. But you can do better (and easier)!
check the stream state with the implicit conversion to void*
which can be used in a bool
context. Since most of the read operations on streams return a reference to the stream, you can write some very consice code like this:
std::string line;
while(std::getline(currentfile, line)) {
// process line
}
Basically what it is doing is saying "while I could successfully extract a line from currentfile
, do the following", which is what you really meant to say anyway ;-);
Like I said, this applies to most stream operations, so you can do things like this:
int x;
std::string y;
if(std::cin >> x >> y) {
// successfully read an integer and a string from cin!
}
EDIT: The way I would rewrite your code is like this:
string line;
unsigned long pos = 0;
int linenumber = 0;
ifstream curfile(input.c_str());
std::cout << "About to try to read the file" << std::endl;
while (std::getline(curfile, line)) {
std::cout << "Getting line " << linenumber << std::endl;
linenumber++;
// do the rest of the work with line
}
回答2:
Do not do it like that.
EOF
is not the only thing you'll encounter while reading. There's a bunch of errors you might get, and so the best is to simply test the stream itself:
while(currentfile)
{
// read somehow
}
If you're reading lines, then, the simplest way is:
std::string line;
while(std::getline(currentfile, line))
{
// use line
}
回答3:
Your first call to getline
is triggering one of the fail-bits on the ifstream
object. That is why if you do a check for a fail-bit using ios::good()
, you never enter your read loop. I would check to see what the value of line
is ... it's probably empty, meaning you're having another issue reading your file, like maybe permissions problems, etc.
回答4:
The problem is here:
if (!curfile.good())
cout<<"Bad file read"<<endl; // OK you print bad.
while (!curfile.eof()) // But the loop is still entered.
// Another reason to **NEVER** to use
// while (file.eof()) // as bad does not mean eof
// though eof is bad
Try this:
void readFile(std::istream& str)
{
std::string line;
while(std::getline(str, line))
{
std::stringstream lineStream(line);
std::string ignoreWord;
int number[3];
lineStream >> ignoreWord // reads one space seporated word
>> number[0] // reads a number
>> ignoreWord >> ignoreWord >> ignoreWords // reads three words
>> number[1] // reads a number
>> number[2]; // reads a number
current.push_back(number[0]);
dx.push_back(number[1]);
dy.push_back(number[2]);
}
}
来源:https://stackoverflow.com/questions/6512173/ifstream-not-reading-eof-character