page contents

C++移动和获取文件读写指针(seekp、seekg、tellg、tellp)

ifstream 类和 fstream 类有 seekg 成员函数,可以设置文件读指针的位置; ofstream 类和 fstream 类有 seekp 成员函数,可以设置文件写指针的位置。

在读写文件时,有时希望直接跳到文件中的某处开始读写,这就需要先将文件的读写指针指向该处,然后再进行读写。

  • ifstream 类和 fstream 类有 seekg 成员函数,可以设置文件读指针的位置;

  • ofstream 类和 fstream 类有 seekp 成员函数,可以设置文件写指针的位置。


所谓“位置”,就是指距离文件开头有多少个字节。文件开头的位置是 0。

这两个函数的原型如下:

ostream & seekp (int offset, int mode);
istream & seekg (int offset, int mode);

mode 代表文件读写指针的设置模式,有以下三种选项:

  • ios::beg:让文件读指针(或写指针)指向从文件开始向后的 offset 字节处。offset 等于 0 即代表文件开头。在此情况下,offset 只能是非负数。

  • ios::cur:在此情况下,offset 为负数则表示将读指针(或写指针)从当前位置朝文件开头方向移动 offset 字节,为正数则表示将读指针(或写指针)从当前位置朝文件尾部移动 offset字节,为 0 则不移动。

  • ios::end:让文件读指针(或写指针)指向从文件结尾往前的 |offset|(offset 的绝对值)字节处。在此情况下,offset 只能是 0 或者负数。


此外,我们还可以得到当前读写指针的具体位置:

  • ifstream 类和 fstream 类还有 tellg 成员函数,能够返回文件读指针的位置;

  • ofstream 类和 fstream 类还有 tellp 成员函数,能够返回文件写指针的位置。


这两个成员函数的原型如下:

int tellg();
int tellp();

要获取文件长度,可以用 seekg 函数将文件读指针定位到文件尾部,再用 tellg 函数获取文件读指针的位置,此位置即为文件长度。

例题:假设学生记录文件 students.dat 是按照姓名排好序的,编写程序,在 students.dat 文件中用折半查找的方法找到姓名为 Jack 的学生记录,并将其年龄改为 20(假设文件很大,无法全部读入内存)。程序如下:




  1. #include <iostream>

  2. #include <fstream>

  3. #include <cstring>

  4. using namespace std;

  5. class CStudent

  6. {

  7. public:

  8. char szName[20];

  9. int age;

  10. };

  11. int main()

  12. {

  13. CStudent s;

  14. fstream ioFile("students.dat", ios::in|ios::out);//用既读又写的方式打开

  15. if(!ioFile) {

  16. cout << "error" ;

  17. return 0;

  18. }

  19. ioFile.seekg(0,ios::end); //定位读指针到文件尾部,

  20. //以便用以后tellg 获取文件长度

  21. int L = 0,R; // L是折半查找范围内第一个记录的序号

  22. // R是折半查找范围内最后一个记录的序号

  23. R = ioFile.tellg() / sizeof(CStudent) - 1;

  24. //首次查找范围的最后一个记录的序号就是: 记录总数- 1

  25. do {

  26. int mid = (L + R)/2; //要用查找范围正中的记录和待查找的名字比对

  27. ioFile.seekg(mid *sizeof(CStudent),ios::beg); //定位到正中的记录

  28. ioFile.read((char *)&s, sizeof(s));

  29. int tmp = strcmp( s.szName,"Jack");

  30. if(tmp == 0) { //找到了

  31. s.age = 20;

  32. ioFile.seekp(mid*sizeof(CStudent),ios::beg);

  33. ioFile.write((char*)&s, sizeof(s));

  34. break;

  35. }

  36. else if (tmp > 0) //继续到前一半查找

  37. R = mid - 1 ;

  38. else  //继续到后一半查找

  39. L = mid + 1;

  40. }while(L <= R);

  41. ioFile.close();

  42. return 0;

  43. }

attachments-2021-05-C16I1JZX60a3845dedf7e.jpg


  • 发表于 2021-05-18 17:10
  • 阅读 ( 821 )
  • 分类:C/C++开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
小柒
小柒

1470 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章