博主头像
小雨淅沥

Some things were meant to be.

OOP课程笔记:第七章 输入输出流类库

第七章 输入输出流类库

1.简介

C++语言的 I/O 系统向用户提供一个统一的接口,使得程序的设计尽量与所访问的具体设备无关,在用户与设备之间提供了一个抽象的界面:输入输出流

用标准流进行输入输出时,系统自动地完成数据类型的转换。

对于输入流,要将输入的字符序列形式的数据变换成计算机内部形式的数据(二进制或 ASCII)后,再赋给变量变换后的格式由变量的类型确定。

对于输出流,将要输出的数据变换成字符串形式后,送到输出流(文件)中。

2.重载输入输出运算符

自定义的对象不能直接输入输出,需要对运算符 << >> 进行重载


重载输入运算符

在对象所在的类中 将重载这二个运算符的函数说明该类的 友元函数

friend istream & operater >>(istream&, ClassName& );     // 在类内的声明
istream & operater >>(istream &is , A &a)                 // 在类外的声明
cin >> a;                // 调用1
operator >> (cin,a)     // 调用2,效果同上    

其中 istream 作为返回值类型, operator作为函数名

istream&作为左操作数,ClassName&作为右操作数

返回值类型:类 istream 的引用, cin 中可以连续使用运算符

cin >> a >> b;
class incount {
    int c1, c2;
public:
    incount(int a = 0, int b = 0) { c1 = a; c2 = b; }
    void show(void) { cout << "c1=" << c1 << "\t" << "c2=" << c2 << endl; }
    friend istream& operator>>(istream&, incount&);// 重载输入函数声明
};

istream& operator>>(istream& is, incount& cc) {
    is >> cc.c1 >> cc.c2;
    return is;
}

void main(void) {
    incount x1, x2;
    x1.show();
    x2.show();
    cin >> x1;
    cin >> x2;
    x1.show();
    x2.show();
}

重载输出运算符

#include <iostream>
using namespace std;

class incount {
    int c1, c2;
public: 
    incount(int a = 0, int b = 0) { c1 = a; c2 = b; }
    void show(void) { cout << "c1=" << c1 << "\t" << "c2=" << c2 << endl; }
    friend istream& operator>>(istream&, incount&);
    friend ostream& operator<<(ostream&, incount&);
};

// 重载输入函数定义
istream& operator>>(istream& is, incount& cc) {
    is >> cc.c1 >> cc.c2;
    return is;
}

// 重载输出函数定义
ostream& operator<<(ostream& os, incount& cc) {
    os << "c1=" << cc.c1 << "\t" << "c2=" << cc.c2 << endl;
    return os;
}

int main() {
    incount x1, x2;
    cout << x1 << x2; // 调用输出函数
    cin >> x1;        // 调用输入函数
    cin >> x2;
    cout << x1 << x2;
    return 0;
}

3.文件流

C++在头文件 fstream.h 中定义了 C++ 的文件流类体系

文件分为使用 ASCII 和 二进制读取 两种方式


文本文件的打开与关闭

在文件操作前,需要将程序与被操作的文件联系起来使程序可以引用文件

在程序内定义一个文件类的对象,由该对象与文件发生联系,程序内所有的与文件的操作都是对该对象的操作 。

fstream infile ,outfile;    // 两个对象,可以联系两个输入输出文件
ifstream infile;    // 输入
ofstream outfile;    // 输出
ifstream infile;
infile.open(“myfile1.txt”)

打开文件 myfile1.txt 用于输入,并将这个文件与输入文件类对象 infile 建立联系

在程序中,用到这个文件 myfile1.txt 的地方就用 infile来代替。

ifstream infile;
ofstream outfile;
infile.open("myfile1.txt");
outfile.open("myfile2.txt");
float x, y;
infile >> x >> y;    // 从文件读取
outfile << x << 't' << y << endl; // 输出到文件
infile.close();    // 使用完则关闭文档
outfile.close();// 使用完则关闭文档

使用 fstream 进行读写

当用类 fstream 定义文件对象时必须在成员函数 open() 中的参数中 给出打开方式(读或写)

pfile1.open(“file1.txt”,ios::in );//pfile1 联系到“ file1.txt”, 用于输入
pfile2.open(“file2.txt”,ios::out );//pfile2 联系到“ file2.txt”, 用于输出

下文展示如何具体写入和读出数据到文件中

#include <iostream>
#include <fstream>
using namespace std;

int main() {
    int a[10];
    ifstream infile;    // 定义输入文件流对象
    ofstream outfile;   // 定义输出文件流对象
    
    infile.open("file1.txt");   // 打开输入文件"file1.txt"
    outfile.open("file2.txt");  // 打开输出文件"file2.txt"
    
    if (!infile) {
        cout << "无法打开输入文件: file1.txt" << endl;
        return 1;
    }
    
    if (!outfile) {
        cout << "无法打开输出文件: file2.txt" << endl;
        return 1;
    }

    for (int i = 0; i < 10; i++) {
        infile >> a[i];  // 从"file1.txt"读取十个整数到数组a
    }

    for (int i = 0; i < 10; i++) {
        outfile << a[i] << "\t";  // 将数组a的十个数写入"file2.txt",用制表符分隔
    }
    outfile << endl;  // 写入换行符

    infile.close();   // 关闭输入文件
    outfile.close();  // 关闭输出文件

    return 0;
}

判断打开成功

在打开文件后,都要判断打开是否成功。若打开成功,则文件流对象值为非零值; 若打开不成功,则其值为 0

打开输入文件时,文件必须存在

打开输出文件时,若文件不存在,则建立文件;若文件存在,则删除原文件的内容,使其成为一个空文件

#include <iostream>
#include <fstream>
#include <cstdlib>  // for exit()
using namespace std;

int main() {
    fstream pfile1, pfile2; // 定义了两个文件类的对象

    pfile1.open("file1.txt", ios::in);
    pfile2.open("file2.txt", ios::out);

    if (!pfile1) {  // 若为0,打开文件操作失败
        cout << "不能打开输入文件:file1.txt" << '\n';
        exit(1);
    }
    
    if (!pfile2) {
        cout << "不能打开输出文件:file2.txt" << '\n';
        exit(1);
    }
    // 文件操作代码...
    pfile1.close();
    pfile2.close();
  
    return 0;
}

常见字符串读写

参见下方,类似于 cincout 的使用

cin.get(ch);            //从键盘输入一个字符
infile.get(ch);            //从文件输入一个字符

cout.put(ch);            //向显示器输出一个字符
outfile.put(ch);        //向文件输出一个字符

cin.getline(str,300);    //从键盘输入一行字符
infile.getline(str,300);//从文件输入一行字符

二进制读写操作

fstream infile,outfile;
infile.open(“inf1.dat”, ios::in|ios::binary);    // 使用二进制输入方式打开
outfile.open(“outf1.dat”, ios::out|ios::binary);

由于二进制文件中的数据不是 ASCII 码,故不能直接对其读写, 必须要通过特定的函数予以转换

具体使用时一般使用 char 类型转换

// 读取单个整数
int i;
infile.read(reinterpret_cast<char*>(&i), sizeof(int));
// 这里使用了强制类型转换:reinterpret_cast<char*>,该方式不做任何的检查

// 读取整数数组
int a[10];
infile.read(reinterpret_cast<char*>(a), 10 * sizeof(int));

// 写入一个整数
int i = 4;
outfile.write(reinterpret_cast<char*>(&i), sizeof(int));

// 写入一个数组
int a[10]={0,1,2,3,4,5,6,7,8,9};
outfile.write(reinterpret_cast<char*a, 10 * sizeof(int));

在二进制的读取中,判断是否读到文件尾部使用 infile.eof()

当到达文件结束位置时,该函数返回一个非零值,否则返回零。

fstream infile;
infile.open("data1.dat",ios::in|ios::binary);
if(!infile)
    cout<<"Open Error!\n"; exit(1);

char str[300];
while(!infile.eof())    // 没有结束就继续读取
    infile.read(str, 300);

完整的代码示例

#include <iostream>
#include <fstream>
#include <cstring>  // For strcpy if needed
using namespace std;

int main() {
    char filename1[256], filename2[256];
    char buff[4096];
    
    cout << "输入源文件名: ";
    cin >> filename1;
    cout << "输入目的文件名: ";
    cin >> filename2;

    fstream infile, outfile;
    infile.open(filename1, ios::in | ios::binary);
    if (!infile) {
        cerr << "无法打开源文件: " << filename1 << endl;
        return 1;
    }

    outfile.open(filename2, ios::out | ios::binary);
    if (!outfile) {
        cerr << "无法创建目标文件: " << filename2 << endl;
        infile.close();
        return 1;
    }

    while (true) {
        infile.read(buff, sizeof(buff));
        streamsize n = infile.gcount();  // 获取实际读取的字节数
        
        if (n > 0) {
            outfile.write(buff, n);
        }
        
        if (infile.eof()) {
            break;  // 到达文件末尾,退出循环
        }
        
        if (!infile) {
            cerr << "文件读取错误" << endl;
            break;
        }
    }

    infile.close();
    outfile.close();

    cout << "文件复制完成" << endl;
    return 0;
}
OOP课程笔记:第七章 输入输出流类库
https://www.rainerseventeen.cn/index.php/Code-Basic/18.html
本文作者 Rainer
发布时间 2025-10-18
许可协议 CC BY-NC-SA 4.0

评论已关闭