C++之文件流操作

open函数和close函数的使用方法

#include <iostream>
#include <exception>
#include <fstream>
#include <cstring>

using namespace std;


int main() {
    const char *text = "niu brother is so good\n";
    const char *text_2 = "niu brother is a good man\n";
    ofstream outfile;
    outfile.open("D://cpp_text.txt", ios::out);
    outfile.write(text, strlen(text));
    outfile.write(text_2, strlen(text_2));
    outfile.close();
    cout << strlen(text) << endl;
    return 0;
}
输出:
23

上述输出的是字符串数组的长度,运行程序生成的文件存在本地的D盘中,文件中的具体内容展示为:
在这里插入图片描述
已知fstream是ios基类的最终的间接派生类,所以它继承了ios基类的所有成员(私有成员除外),ios基类直接派生出了ostream类和istream类,而ostream类派生出了ofstream类和iostream类,istream类派生出了ifstream类和iostream类,而fstream是iostream的派生类。所以fstream拥有istream,ostream,iostream,ios基类的全部成员。
open()有两个参数,第一个参数是指向文件名的指针,第二个参数是打开文件的模式,这里定义为写入模型。注:若一开始不存在打开的文件,系统会自动创建该文件再写入。
下面来看一下文件打开的各种模式

模式标记适用对象作用
ios::inifstream fstream打开文件用于读取数据,如果文件不存在,则打开出错
ios::outofstream fstream打开文件用于写入数据,如果文件不存在,则新建该文件,如果文件存在,则打开时清除原来的内容。
ios::appofstream fstream打开文件,用于在其尾部添加数据,如果文件不存在,则新建该文件。
ios::ateifstream打开一个已有的文件,并将文件读指针指向文件末尾,如果文件不存在,则打开出错。
ios::truncofstream打开文件时会清空内部存储的所有数据,单独使用时与ios::out相同。
ios::binaryifstream ofstream fstream以二进制方式打开文件。若不指定此模式,则以文本模式打开。
ios::in丨ios::outfstream打开已存在的文件,既可读取其内容,也可向其写入数据。文件刚打开时,原有内容保持不变,如果文件不存在,则打开出错。
ios::in 丨 ios::outofstream打开已存在的文件,可以向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。
ios::in 丨ios::out 丨ios::truncfstream打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容,若文件不存在,则新建该文件。

ios::binary 可以和其他模式标记组合使用,例如:
ios::in | ios::binary 表示二进制模式以读取的方式打开
ios::out | ios::binary 表示二进制模式以写入的方式打开

我们知道,调用 open() 方法打开文件,是文件流对象和文件之间建立关联的过程。那么,调用 close() 方法关闭已打开的文件,就可以理解为是切断文件流对象和文件之间的关联。注意,close() 方法的功能仅是切断文件流与文件之间的关联,该文件流并会被销毁,其后续还可用于关联其它的文件。打开的文件流用完之后一定要close掉,不然会造成内存泄漏的风险。

文本文件读写操作详解

上面已经介绍过文件流对象如何调用open()打开文件,并在I/O文件操作结束后,调用close()方法关闭先前打开的文件。那么如何对文件内容实现读写呢?下面来详细介绍一下。

对文件的I/O操作可以细分为两类,分别是以文本形式读写文件和以二进制形式读写文件。
1.我们知道,文件中存储的数据并没有类型上的分别,统统都是字符。所谓以文本形式读/写文件,就是直白地将文件中存储的字符(或字符串)读取出来,以及将目标字符(或字符串)存储在文件中。
2.而以二进制形式读/写文件,操作的对象不再是打开文件就能看到的字符,而是文件底层存储的二进制数据。更详细地讲,当以该形式读取文件时,读取的是该文件底层存储的二进制数据;同样,当将某数据以二进制形式写入到文件中时,写入的也是其对应的二进制数据。
举个例子,假设我们以文本形式将浮点数 19.625 写入文件,则该文件会直接将 “19.625” 这个字符串存储起来。当我们双击打开此文件,也可以看到 19.625。值得一提的是,由非字符串数据(比如这里的浮点数 19.625)转换为对应字符串(转化为 “19.625”)的过程,C++ 标准库已经实现好了,不需要我们操心。
但如果以二进制形式将浮点数 19.625 写入文件,则该文件存储的不再是 “19.625” 这个字符串,而是 19.625 浮点数对应的二进制数据。
0100 0001 1001 1101 0000 0000 0000 0000
显然,如果直接将以上二进制数据转换为 float 类型,仍可以得到浮点数 19.625。但对于文件来说,它只会将存储的二进制数据根据既定的编码格式(如 utf-8、gbk 等)转换为一个个字符。这也就意味着,如果我们直接打开此文件,看到的并不会是 19.625,往往是一堆乱码。
C++ 标准库中,提供了 2 套读写文件的方法组合,分别是:
1.使用 >> 和 << 读写文件:适用于以文本形式读写文件;
2.使用 read() 和 write() 成员方法读写文件:适用于以二进制形式读写文件。

C++ >>和<<读写文本文件

我们知道fstream 或者 ifstream 类负责实现对文件的读取,它们内部都对 >> 输出流运算符做了重载;同样,fstream 和 ofstream 类负责实现对文件的写入,它们的内部也都对 << 输出流运算符做了重载。
所以,当 fstream 或者 ifstream 类对象打开文件(通常以 ios::in 作为打开模式)之后,就可以直接借助 >> 输入流运算符,读取文件中存储的字符(或字符串);当 fstream 或者 ofstream 类对象打开文件(通常以 ios::out 作为打开模式)后,可以直接借助 << 输出流运算符向文件中写入字符(或字符串)。

#include <iostream>
#include <fstream>
#include <cstring>

using namespace std;

int main() {
    int x;
    int sum = 0;
    ofstream ofs;
    ifstream ifs;
    const char *read_src = "D://cpp_text.txt";
    const char *write_src = "D://cpp_write.txt";
    const char *init_text = "20 30 60\n50 20";
    ofs.open(read_src, ios::out);
    ofs.write(init_text, strlen(init_text));
    ofs.close();
    try {
        ifs.open(read_src, ios::in);
        ofs.open(write_src, ios::out);
        while (ifs >> x) {
            sum += x;
            cout << "x_in:" << x << endl;
            ofs << x << "\n";
        }
        cout << "sum:" << sum << endl;
    } catch (exception &e) {
        cout << "failed the open the file" << endl;
    }
    ifs.close();
    ofs.close();
    ifs.open(write_src, ios::in);
    while (ifs >> x) {
        cout << "x_out:" << x << endl;
    }
    ifs.close();
    return 0;
}
输出:
x_in:20
x_in:30
x_in:60
x_in:50
x_in:20
sum:180
x_out:20
x_out:30
x_out:60
x_out:50
x_out:20

执行此程序之前,必须在和系统中对应的硬盘下中手动创建一个 cpp_text.txt 文件,假设其内部存储的字符串为:

10 20 60
50 20

建立之后,执行程序,其执行结果为:
sum:180
同时在 cpp_text.txt 文件同目录下,会生成一个 cpp_write.txt 文件,其内部存储的每一个字符都独占一行。
通过分析程序的执行结果不难理解,对于 cpp_text.txt 文件中的"10 20 30 40 50"字符串,ifs对象会依次将"10"、“20”、“30”、“40”、“50” 读取出来,将它们解析成 int 类型的整数 10、20、30、40、50 并赋值给 x,同时完成和 sum 的加和操作。
同样,对于每次从 cpp_text.txt 文件读取并解析出的整型 x,ofs对象都会原封不动地将其再解析成对应的字符串(如整数 10 解析成字符串 “10”),然后和 " " 空格符一起写入 cpp_write.txt 文件。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值