STL: std::ifstream 使用eof会多读一行数据
## Error Description
STL: std::ifstream 使用eof会多读一行数据
```cpp
string dataset_dir = "Dataset_DIR";
cout << "dataset: " << dataset_dir << endl;
ifstream fin("f3_w_static_associations.txt");
if (!fin) {
cout << "please generate the associate file called associations.txt!" << endl;
fin.close();
return 1;
}
vector rgb_files, depth_files;
vector rgb_times, depth_times;
while (!fin.eof()) {
string rgb_time, rgb_file, depth_time, depth_file;
fin >> rgb_time >> rgb_file >> depth_time >> depth_file;
rgb_times.push_back(atof(rgb_time.c_str()));
depth_times.push_back(atof(depth_time.c_str()));
rgb_files.push_back(dataset_dir + "/" + rgb_file);
depth_files.push_back(dataset_dir + "/" + depth_file);
if (fin.good() == false)
break;
}
fin.close();
```
我读取TUM数据集的时候,会发现会出现段错误:
```sh
************ Current Frame: 717 ************
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr: __pos (which is 140) > this->size() (which is 0)
Thread 1 "run_vo" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff4ac4e97 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff4ac6801 in __GI_abort () at abort.c:79
#2 0x00007ffff511b957 in () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff5121ab6 in () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ffff5121af1 in () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ffff5121d24 in () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ffff511d855 in () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007ffff5dbc4e8 in () at /usr/lib/x86_64-linux-gnu/libopencv_imgcodecs.so.3.2
#8 0x00007ffff5daee64 in () at /usr/lib/x86_64-linux-gnu/libopencv_imgcodecs.so.3.2
#9 0x00007ffff5db476a in () at /usr/lib/x86_64-linux-gnu/libopencv_imgcodecs.so.3.2
#10 0x00007ffff5db532d in cv::imread(cv::String const&, int) ()
at /usr/lib/x86_64-linux-gnu/libopencv_imgcodecs.so.3.2
#11 0x0000555555558e5c in main(int, char**) (argc=, argv=)
at /root/catkin_ws/src/aivslam/test/run_vo.cpp:66
(gdb)
```
原因在于读取图像数据 cv::imread(cv::String const&, int)时,所传入的参数非法。
问题在于eof上。
在 https://blog.csdn.net/u011028345/article/details/76563198 博客上看到:
> eof是end of file的意思,用来判断是否到了文件结尾。 按照一般思维,应该就是到达文件尾,就eof()应返回true,但事实上,在读完最后一个数据时,eofbit仍然是false。只有当流再往下读取时,发现文件已经到结尾了,才会将标志eofbit修改为true。这也就是为什么使用while(!readfile.eof())会出多现读一行的原因。
的确是这样的。
# Solution
使用 getline()或加上判空。
## Example 1:
```cpp
void LoadImages(const string &strAssociationFilename, vector &vstrImageFilenamesRGB,
vector &vstrImageFilenamesD, vector &vTimestamps)
{
ifstream fAssociation;
fAssociation.open(strAssociationFilename.c_str());
while (!fAssociation.eof())
{
string s;
getline(fAssociation, s);
if (!s.empty())
{
stringstream ss;
ss << s;
double t;
string sRGB, sD;
ss >> t;
vTimestamps.push_back(t);
ss >> sRGB;
vstrImageFilenamesRGB.push_back(sRGB);
ss >> t;
ss >> sD;
vstrImageFilenamesD.push_back(sD);
}
}
}
```
## Example 2:
```cpp
// reading a text file
#include
#include
#include
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
```
## My Example
```cpp
string dataset_dir = "Dataset_DIR";
cout << "dataset: " << dataset_dir << endl;
ifstream fin("f3_w_static_associations.txt");
if (!fin) {
cout << "please generate the associate file called associations.txt!" << endl;
fin.close();
return 1;
}
vector rgb_files, depth_files;
vector rgb_times, depth_times;
while (!fin.eof()) {
string rgb_time, rgb_file, depth_time, depth_file;
fin >> rgb_time >> rgb_file >> depth_time >> depth_file;
if (!rgb_file.empty() && !depth_file.empty()) {
rgb_times.push_back(atof(rgb_time.c_str()));
depth_times.push_back(atof(depth_time.c_str()));
rgb_files.push_back(dataset_dir + "/" + rgb_file);
depth_files.push_back(dataset_dir + "/" + depth_file);
}
if (fin.good() == false)
break;
}
fin.close();
if (rgb_files.size() != depth_files.size()) {
cout << "RGB image size NOT equal to depth image size" << endl;
return 1;
```
![yubao_blog_cover](https://raw.githubusercontent.com/yubaoliu/assets/image/yubao_blog_cover.png)
No comments