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

前言

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


读写指针

  • 输入流的read指针
  • 输出流的write指针

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


文本文件读写demo

cpp 复制代码
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <vector>
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 

二进制文件读写demo1


cpp 复制代码
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <vector>
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;
}

二进制文件读写demo2

  • 先写入三个对象的数据
cpp 复制代码
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <vector>
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
  • 读出并合理地显示内容
cpp 复制代码
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <vector>
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

二进制文件读写demo3

  • 用一个fstream流对象完成读和写的任务
cpp 复制代码
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <vector>
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

总结

  • 文本模式和二进制模式的主要区别在于文本模式会执行一些与文本数据处理相关的特殊转换和处理(比如Windows下所有的'\r\n'会被解释成一个'\n'字符,从而造成数据读取泄漏),而二进制模式不会执行这些操作,二进制模式保留原数据。
  • 这里写入、读出时总利用char*作为参数的其中之一作用:是为了更好地观察、理解数据,否则其他数据类型打开在用户视角是一片乱码(可以用记事本打开dat文件验证)。
相关推荐
luj_17687 小时前
残熵算法实时化三大瓶颈突破
c语言·开发语言·网络·经验分享·算法
不听话坏7 小时前
Ignition篇(下 一) 动态执行前的事情
开发语言·前端·javascript
likeyi078 小时前
require 和 import的区别
开发语言·前端
远离UE48 小时前
UE5 compute shader 原子加
开发语言·c++·ue5
C+-C资深大佬8 小时前
C++ 显式类型转换详解:static_cast、dynamic_cast、const_cast、reinterpret_cast
开发语言·c++
KaMeidebaby9 小时前
卡梅德生物技术快报|抗体亲和力成熟工业化调控新机制:差异性浆细胞增殖工艺优化思路
java·开发语言·人工智能·算法·机器学习·架构·spark
luj_17689 小时前
心形曲线轨迹控制三大关键技术
c语言·开发语言·c++·经验分享·算法
取地址符10 小时前
C++学习笔记(基于learn-cxx)(1)
c++·经验分享·笔记·学习
Mininglamp_271810 小时前
Claude Code 封禁中国开发者之后:本地 AI 编程工具的替代方案实测
开发语言·人工智能·windows·开源软件·ai-native
思麟呀10 小时前
C++17(三)if constexpr+折叠表达式
开发语言·c++