• 北大C++课后记录:文件读写的I/O流


    前言

    文件和平常用到的cincout流其实是一回事,可以将文件看作一个有限字符构成的顺序字符流,基于此,也可以像cincout读键盘数据那样对文件进行读写。


    读写指针

    • 输入流的read指针
      在这里插入图片描述
    • 输出流的write指针
      在这里插入图片描述

    注:这里的指针并不是普通的内存指针(*ptr),而是一种叫std::streampos类型的指针,是用于在文件流中定位文件位置的数据类型,可以类比成一个int型的数据。


    文本文件读写demo

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    int main(){
        vector<int> v;
        ifstream srcFile("testin.txt", ios :: in);
        ofstream destFile("testout.txt", ios :: out);
        int t;
        while(srcFile >> t)
            v.push_back(t);
        sort(v.begin(), v.end());
        for(auto i : v)
            destFile << i << ' ';
    
        //不执行close的话数据还在内存(的缓冲区)里没被磁盘读走
        srcFile.close();
        destFile.close();
        return 0;
    }
    //testin.txt: 9 84 23 15 56 2 34 123 5 1
    //testout.txt: 1 2 5 9 15 23 34 56 84 123 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    二进制文件读写demo1

    在这里插入图片描述
    在这里插入图片描述

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    //写入一个整型数据后接着读出
    int main(){
        ofstream fout("some.bat", ios::out | ios::binary);      //从文件头开始,以二进制的形式写入
        int x = 120;
        //从x的内存地址开始传入4字节数据
        //(const char*)强转是为了让编译器拿到(int*)指针后能将其解释成字符型数据
        fout.write((const char*) &x, sizeof(int));
        fout.close();
        int y;
        ifstream fin("some.bat", ios::in | ios::binary);//从文件头开始,以二进制的形式写入
        //从文件开头处取出4字节数据
        //然后将y地址转成(char*)从而在该地址后面放入4字节数据
        fin.read((char*) &y, sizeof(int));
        fin.close();
        cout << y << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    二进制文件读写demo2

    • 先写入三个对象的数据
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    struct Student{
        char name[20];
        int score;
    };//24-Byte
    
    int main(){
        Student s;
        ofstream OutFile("students.dat", ios::out|ios::binary);
        while(cin >> s.name >> s.score)
            OutFile.write((char*) &s, sizeof(s));
        OutFile.close();
        return 0;
    }
    //input:
    //Tom 60
    //Jack 80
    //Jane 40
    //^Z Enter
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 读出并合理地显示内容
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    struct Student{
        char name[20];
        int score;
    };//24-Byte
    
    int main(){
        Student s;
        ifstream inFile("students.dat", ios::in|ios::binary);
        if(!inFile){        //空流
            cerr << "error" << endl;
            return 0;
        }
        while(inFile.read((char*) &s, sizeof(s))){
            int readBytes = inFile.gcount();	//本次读进来了多少字节数据
            cout << "readBytes: " << readBytes << endl;
            cout << s.name << " " << s.score << endl;
        }
        inFile.close();
        return 0;
    }
    //output:
    //readBytes: 24
    //Tom 60
    //readBytes: 24
    //Jack 80
    //readBytes: 24
    //Jane 40
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    二进制文件读写demo3

    • 用一个fstream流对象完成读和写的任务
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    struct Student{
        char name[20];
        int score;
    };//24-Byte
    //Jane——>Mike
    int main(){
        Student s;
        fstream iofile("students.dat", ios::in|ios::out|ios::binary);
        if(!iofile){
            cerr << "error" << endl;
            return 0;
        }
        iofile.seekp(2 * sizeof(s), ios::beg);      //从文件头开始将写指针移动两个对象大小的跨度——>到第三个对象的首字节
        //由于Mike和Jane同字符个数,所以写入Mike后'e'的后面已经是'\0'了,其实可以不“+1”让编译器来补终止符。
        iofile.write("Mike", strlen("Mike") + 1);       
        iofile.seekg(0, ios::beg);      //防止读指针随机指到其他地方
        while(iofile.read((char*) &s, sizeof(s))){
            int readBytes = iofile.gcount();
            cout << "readByte: " << readBytes << endl;
            cout << s.name << " " << s.score << endl;
        }
        iofile.close();
        return 0;
    }
    // output:
    // readByte: 24
    // Tom 60
    // readByte: 24
    // Jack 80
    // readByte: 24
    // Mike 40
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    总结

    • 文本模式和二进制模式的主要区别在于文本模式会执行一些与文本数据处理相关的特殊转换和处理(比如Windows下所有的'\r\n'会被解释成一个'\n'字符,从而造成数据读取泄漏),而二进制模式不会执行这些操作,二进制模式保留原数据。
    • 这里写入、读出时总利用char*作为参数的其中之一作用:是为了更好地观察、理解数据,否则其他数据类型打开在用户视角是一片乱码(可以用记事本打开dat文件验证)。
  • 相关阅读:
    第五章 Jest进行前端单元测试
    2022年最新西藏水利水电施工安全员考试题库及答案
    计算机竞赛 机器学习股票大数据量化分析与预测系统 - python 计算机竞赛
    springboot快速搭建ftpserver服务端
    electron文档
    AIGC创作系统ChatGPT源码,支持最新GPT-4-Turbo模型,支持DALL-E3文生图
    Java方法的重载/方法的内存/基本数据类型与引用数据类型/方法的值传递
    Windows系统无NVIDIA卡安装APEX
    Java == 和 equals()
    HTTP Mime-Type对照表
  • 原文地址:https://blog.csdn.net/weixin_53024141/article/details/132920953