C++移动和获取文件读写指针

简介: 在读写文件时,有时希望直接跳到文件中的某处开始读写,这就需要先将文件的读写指针指向该处,然后再进行读写。ifstream 类和 fstream 类有 seekg 成员函数,可以设置文件读指针的位置;ofstream 类和 fstream 类有 seekp 成员函数,可以设置文件写指针的位置。所谓“位置”,就是指距离文件开头有多少个字节。文件开头的位置是 0。这两个函数的原型如下:ostream & seekp (int offset, int mode);istream & seekg (int offset, int mode);mode 代表文件读写指针的设置模

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

  • 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(假设文件很大,无法全部读入内存)。程序如下:

#include <iostream>
    #include <fstream>
    #include <cstring>
    using namespace std;
    class CStudent
    {
        public:
            char szName[20];
            int age;
    };
    int main()
    {
        CStudent s;       
        fstream ioFile("students.dat", ios::in|ios::out);//用既读又写的方式打开
        if(!ioFile) {
            cout << "error" ;
            return 0;
        }
        ioFile.seekg(0,ios::end); //定位读指针到文件尾部,
                                  //以便用以后tellg 获取文件长度
        int L = 0,R; // L是折半查找范围内第一个记录的序号
                      // R是折半查找范围内最后一个记录的序号
        R = ioFile.tellg() / sizeof(CStudent) - 1;
        //首次查找范围的最后一个记录的序号就是: 记录总数- 1
        do {
            int mid = (L + R)/2; //要用查找范围正中的记录和待查找的名字比对
            ioFile.seekg(mid *sizeof(CStudent),ios::beg); //定位到正中的记录
            ioFile.read((char *)&s, sizeof(s));
            int tmp = strcmp( s.szName,"Jack");
            if(tmp == 0) { //找到了
                s.age = 20;
                ioFile.seekp(mid*sizeof(CStudent),ios::beg);
                ioFile.write((char*)&s, sizeof(s));
                break;
            }
            else if (tmp > 0) //继续到前一半查找
                R = mid - 1 ;
            else  //继续到后一半查找
                L = mid + 1;
        }while(L <= R);
        ioFile.close();
        return 0;
    }
相关文章
|
4天前
|
存储 分布式数据库 API
技术好文:VisualC++查看文件被哪个进程占用
技术好文:VisualC++查看文件被哪个进程占用
|
6天前
|
存储 安全 编译器
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
33 5
|
5天前
|
C++ 容器
【编程技巧】 C++11智能指针
C++11引入了智能指针以自动管理内存,防止内存泄漏和悬挂指针: - `shared_ptr`:引用计数,多所有权,适用于多个对象共享资源。 - `unique_ptr`:独占所有权,更轻量级,适用于单一对象所有者。 - `weak_ptr`:弱引用,不增加引用计数,解决`shared_ptr`循环引用问题。 ## shared_ptr - 支持引用计数,所有者共同负责资源释放。 - 创建方式:空指针、new操作、拷贝构造/移动构造,以及自定义删除器。 - 提供`operator*`和`operator-&gt;`,以及`reset`、`swap`等方法。 ## unique_ptr
|
8天前
|
存储 Java C#
C++语言模板类对原生指针的封装与模拟
C++|智能指针的智能性和指针性:模板类对原生指针的封装与模拟
|
6天前
|
C++
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
7 0
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
|
8天前
|
C++ iOS开发 开发者
C++一分钟之-文件输入输出(I/O)操作
【6月更文挑战第24天】C++的文件I/O涉及`ifstream`, `ofstream`和`fstream`类,用于读写操作。常见问题包括未检查文件打开状态、忘记关闭文件、写入模式覆盖文件及字符编码不匹配。避免这些问题的方法有:检查`is_open()`、显式关闭文件或使用RAII、选择适当打开模式(如追加`ios::app`)以及处理字符编码。示例代码展示了读文件和追加写入文件的实践。理解这些要点能帮助编写更健壮的代码。
16 2
|
4天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
11 0
|
4天前
|
IDE 开发工具 C++
插件:CLion中使用C/C++ Single File Execution插件编译和运行单个文件
插件:CLion中使用C/C++ Single File Execution插件编译和运行单个文件
11 0
|
6天前
|
C++
C++指针
C++指针
8 0
|
5天前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)