实战中遇到的C++流文件重置的一个大陷阱: 为什么ifstream的seekg函数无效?

来源:互联网 发布:淘宝网wap访客是 编辑:程序博客网 时间:2024/06/03 10:38

        今天下午遇到这样的一个问题: 逐行读取了test.txt文件后,  后续需要继续从头开始重新逐行读取, 用C++怎么做呢? 

       下面, 我们先在工程当前目录下制作我们需要的test.txt文件, 在里面输入几行字符串:

ab
cd


ef
gh


         我们先看逐行读取文件:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}return 0;}

      现在, 我们读了一次整个文件后, 又要读, 用下面的方法肯定不行:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}// 不会进入下面的ifif(in){cout << "test" << endl;while(getline(in, line)){cout << line.c_str() << endl;}}return 0;}

      回忆一下, 在C语言中, 我们有文件指针重置的概念, 所以这里我们是不是要考虑一下文件重置呢?看:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}in.seekg(0, ios::beg); // 指向begin处// 仍然不会进入下面的ifif(in){cout << "test" << endl;while(getline(in, line)){cout << line.c_str() << endl;}}return 0;}

       还是没有作用, 难道要close然后open? 在C语言中, close并open后, 肯定指向文件头部了, 于是继续尝试:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}in.close();in.open("test.txt");// 仍然不会进入下面的ifif(in){cout << "test" << endl;while(getline(in, line)){cout << line.c_str() << endl;}}return 0;}
       还是不行, 难道close, open之后还需要seekg? 看:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}in.close();in.open("test.txt");in.seekg(0, ios::beg); // 指向begin处// 仍然不会进入下面的ifif(in){cout << "test" << endl;while(getline(in, line)){cout << line.c_str() << endl;}}return 0;}

       还是不行, 邪门了! 不能再鲁莽地尝试了, 查找资料, 终于找到了问题的关键。

       看程序:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}if(in.eof()){cout << "end of file" << endl; // 进入到了这里}else{cout << "in the file" << endl;}return 0;}

       由上面的例子可知, 达到文件尾巴后, 再调用seekg无效, 那怎么办呢? 且看:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}in.clear();if(in.eof()){cout << "end of file" << endl; }else{cout << "in the file" << endl; // 进入到了这里}return 0;}
      恩, clear功能真大啊, 好, 我们顺着这个思路继续看:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}in.clear();// 会进入下面的if, 但不会进入whileif(in){cout << "test" << endl;while(getline(in, line)){cout << line.c_str() << endl;}}return 0;}

      恩, 貌似还差点什么吧, 对, 还需要将文件重置到头部, 如下:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}in.clear();in.seekg(0, ios::beg); // 指向begin处// 会进入下面的if和whileif(in){cout << "test" << endl;while(getline(in, line)) // 与上面while功能一样{cout << line.c_str() << endl;}}return 0;}

       总算是ok了。
      

       最后看一个程序:

#include <iostream>#include <fstream>#include <string>using namespace std;int main(){ifstream in("test.txt");string line;in.seekg(0, ios::end);cout << in.tellg() << endl; // 文件大小if(in.eof()){cout << "end of file" << endl; }else{cout << "in the file" << endl; // 进入到了这里}// in the file,  所以下面语句有效in.seekg(0, ios::beg); // 指向begin处// 下面代码有效if(in){while(getline(in, line)){cout << line.c_str() << endl;}}return 0;}

       综上所述: seekg(0, ios::end)不是end of file.

                           end of file的时候, seek是无效的, 必须先clear.


       



4 0
原创粉丝点击