C++文件输入输出,看这一篇就够了

1 简介

1.1 继承关系

基类->继承类:

​ ios->ostream->ofstream

​ ios->istream->ifstream

​ iostream->fstream(还继承了两个缓冲区,一个用于输入,一个用于输出)(此类用于文件I/O的同步,即协调地移动输入缓冲区的输入指针和输出缓冲区的输出指针)(输入输出模式时使用fstream类)

1.2 流

C++程序将文件输入和输出看作字符流;对于输入来说,程序从输入流中抽取字符,对于输出来说,程序向输出流中插入字符。流是程序与流源或流目的之间的中介,这样C++就可以对来源不同的字符做相同处理。

1.3 缓冲区

缓冲区就是一块存储空间,它是为了匹配程序处理速度和外设处理速度;比如程序一次处理1byte,但是磁盘一次读取512bytes;又或者程序一次处理1byte,可以1byte地从磁盘读取,但是由于硬件读取一次数据复杂且操作慢,因此使用缓冲区可以加快程序处理速度。

flushing the buffer:刷新缓冲区就是清空缓冲区地内容以备下次使用。

文件输出输入使用缓冲区,在声明每个ofsream or ifsream对象时程序会为其自动分配该对象自己的缓冲区;使用缓冲区可以提高文件输出速度。
何时清空缓存:
1.缓存区满时
2.使用文件close()方法时,为了保证关闭文件时文件被更新。

2 输入输出流状态

流状态被定义为iostate,是由三个ios_base组成:eofbit, badbit, 和failbit,三者都为一位可以设置位1(设置)或0(清除)。当三者都为0时说明一切顺利。

成员 描述
eofbit 当读取文件到达文件尾时置为1
failbit 当输入流中的数据类型和目的数据类型不一致时置为1;I/O错误(读取一个不允许访问的只读磁盘或打开一个不存在的文件)时置为1
badbit 在一些无法诊断的失败破坏流时置为1
goodbit 另一种说明0的方法
good() 如果流可以使用,则返回true,反之返回false
eof() 如果eofbit被设置,则返回true,反之返回false
bad() 如果badbit被设置,则返回true,反之返回false
fail() 如果failbit或badbit被设置,返回true,反之返回false
rdstate() 返回流状态
exceptions() 返回一个位掩码,指出哪些标记导致异常被引发
exceptions(iostate ex) 设置哪些状态将导致clear()引发异常
clear(iostate s) 将流状态设置为s,s的默认值为0;如果rdstate() & exceptions()) != 0,将抛出basic_ios::failure异常;将会设置s,但是其他的会被置0
setstate (iostate s) 调用clear(rdstate()|s)。这将设置与s中设置的位对应的流的状态位,其他流状态保持不变。

2.1 设置状态

setstate()的主要目的是提供一种修改状态的途径。例如,如果num是一个int,则下面的调用将可能导致operator>>(int &)使用setstate()设置failbit或eofbit。

clear();//清除所有的位
clear(eofbit);//清除当前的位并设置为指定的位
setstate(eofbit);//设置指定的位
//等等

2.2 文件尾EOF

文件尾 EOF
如果输入来自于文件:使用文件尾(EOF)判断文件是否读完。
当检测到EOF之后:cin将eofbit和failbit都设置为1;同时,将设置cin对象中的一个指示EOF条件的标记,设置这个标记后,cin将不读取输入,直到cin.clear()。
EOF被定义为值为-1,因此不能将EOF赋给char类型,因为char类型没有符号,需要使用int类型接收EOF。

举例:Windows允许通过键盘模拟文件尾:Ctrl+Z

3 文件传输模式

ios_base定义了openmode类型表示模式,类似于fmtflags和iostate类型,是bitmask类型。

文件模式常量:

Constant Meaning
ios_base::in 读取文件
ios_base::out 写入文件
ios_base::ate 打开文件时文件指针指向文件尾
ios_base::app 在文件尾添加内容
ios_base::trunc 如果文件存在则截断它
ios_base::binary 二进制文件

文件模式组合(|符号表示联合两个二进制为一个值,该值可以表达两个二进制模式)

C++ 模式 C模式 含义
ios_base::in “r” 读文件模式
ios_base::out “w” 与ios_base::out | ios_base::trunc一样
ios_base::out | ios_base::trunc “w” 写文件模式,并且在打开文件时截断文件(将文件置为空)
ios_base::out | ios_base::app “a” 追加模式,将文件指针指向文件尾,向末尾添加内容;原始数据不可修改
ios_base::in | ios_base::out “r+” 打开以读写,在文件允许的位置写入
ios_base::in | ios_base::out | ios_base::trunc “w+” 打开以读写,如果文件已经存在,则首先截断文件
c++mode | ios_base::binary “cmodeb” 在C++模式和二进制模式打开
c++mode | ios_base::ate “cmode” 以指定的模式打开,并将文件指针移到文件尾。

模式的使用方法:

//第二个参数指定模式
//ifstream fin(filename, c++mode);
//fopen(filename, cmode);
ifstream fin("banjo", mode1); // constructor with mode argument
ofstream fout();
fout.open("harp", mode2); // open() with mode arguments

ifstream open()的默认模式为ios_base::in;

ofstream open()的默认模式为ios_base::out | ios_base::trunc;

fstream无默认模式,因此在创建fstream对象时要显示提高模式实参。

4 相关函数

4.1 ofstream对象 or ifstream对象.open(filename)

可以接受C-风格字符串作为参数,也可以接受存储在数组中的字符串
默认情况下,当filename所指文件不存在时,open()将在当前程序可执行目录创建名为filename的文件;
作用:当存在时,open()将首先截断该文件,即删除原有的文件内容,然后再将新内容输出到文件中

4.2 ofstream对象 or ifstream对象.close()

作用:无参数,原因是ofstream对象 or ifstream对象已经关联文件,不需要参数;在关闭文件时,不会释放ofstream对象 or ifstream对象的缓冲区,只是解除了ofstream对象 or ifstream对象与文件的关联关系;ofstream对象 or ifstream对象可以重新与其他文件绑定。

4.3 ofstream对象 or ifstream对象.isopen(filename)

检查文件filename是否被成功打开;如果成功打开,则返回true;反之(文件不存在等原因),返回false。

在流状态中的fin.fail()和fin.good()也能检查文件是否被正常打开,但是流状态相关函数不涉及文件传输模式;但是is_open()考虑了文件传输模式,因此is_open()更适用于检查文件是否正常打开。

4.4 ifstream对象.get(char ch)

作用:逐个字符获取文件中的内容,并将其赋值给ch;直到遇见文件尾。

4.5 ofstream对象.write( (char *) &pl, size);

第一个参数为要写入文件内容的地址(必须转换为char *类型),第二个参数为要写入内容的大小(单位为byte)。

作用:将pl指向的大小为size的内容复制到ofstream对象绑定的文件中。

注意事项:这个方法可以用于不含虚函数的类,原因是在这种情况下,只有数据成员被保存,而方法不会被保存;如果类有虚方法,则也将复制隐藏指针(该指针指向虚函数的指针表);由于下一次运行程序时,虚函数表可能在不同的位置,因此将文件中的旧指针信息复制到对象中,可能造成混乱。

4.6 ifstream对象.read((char *) &pl, size);

第一个参数为读入文件的存储地址(必须转换为char *类型),第二个参数为要读入内容的大小(单位为byte)。

作用:将ifstream对象绑定的文件中大小为size的内容pl指向的地址。

注意事项:这个方法可以用于不含虚函数的类,原因是在这种情况下,只有数据成员被保存,而方法不会被保存;如果类有虚方法,则也将复制隐藏指针(该指针指向虚函数的指针表);由于下一次运行程序时,虚函数表可能在不同的位置,因此将文件中的旧指针信息复制到对象中,可能造成混乱。

4.7 fstream对象 or istream对象.seekg()

将输入指针移动至给定文件位置(由于fstream对象使用缓冲区存取中间数据,因此指针指向的实际上是缓冲区的位置,而不是实际的文件)。

也可以将seekg()用于ifstream对象。

函数原型:

第一个原型定位到离第二个参数指定的文件位置的偏移量(单位为字节)的位置,第一个参数off_type为偏移量,第二个参数ios_base::seekdir可以为三个常量—ios_base::beg(相对于文件开始处的偏移)、ios_base::cur(相对于文件当前位置的偏移)、ios_base::end(相对于文件结尾处的偏移);

第二个原型定位到离文件开头特定距离(单位为字节)的位置,参数pos_type为偏移量。是一个绝对偏移量。

//模板原型
basic_istream<charT,traits>& seekg(off_type, ios_base::seekdir);
basic_istream<charT,traits>& seekg(pos_type);
//For the char specialization
istream & seekg(streamoff, ios_base::seekdir);
istream & seekg(streampos);//streampos包含一个接收streamoff参数的构造函数和一个接收整数参数的构造函数

//eg
fin.seekg(30, ios_base::beg); // 30 bytes beyond the beginning
fin.seekg(-1, ios_base::cur); // back up one byte
fin.seekg(0, ios_base::end); // go to the end of the file

注意:streampos和streampos是off_type和pos_type对于char类型的专门化;同样,针对wistream对象,wstreampos和streamoff类型是off_type和pos_type对于wistream类型的专门化。

4.8 fstream对象 or ostream对象.seekp()

将输出指针移动至给定文件位置(由于fstream对象使用缓冲区存取中间数据,因此指针指向的实际上是缓冲区的位置,而不是实际的文件)。

也可以将seekp()用于ofstream对象。

将输出指针移动至给定文件位置(由于fstream对象使用缓冲区存取中间数据,因此指针指向的实际上是缓冲区的位置,而不是实际的文件)。

也可以将seekp()用于ofstream对象。

函数原型:

第一个原型定位到离第二个参数指定的文件位置的偏移量(单位为字节)的位置,第一个参数off_type为偏移量,第二个参数ios_base::seekdir可以为三个常量—ios_base::beg(相对于文件开始处的偏移)、ios_base::cur(相对于文件当前位置的偏移)、ios_base::end(相对于文件结尾处的偏移);

第二个原型定位到离文件开头特定距离(单位为字节)的位置,参数pos_type为偏移量。是一个绝对偏移量。

//模板原型
basic_istream<charT,traits>& seekp(off_type, ios_base::seekdir);
basic_istream<charT,traits>& seekp(pos_type);
//For the char specialization
istream & seekp(streamoff, ios_base::seekdir);
istream & seekp(streampos);//streampos包含一个接收streamoff参数的构造函数和一个接收整数参数的构造函数

//eg
fin.seekp(30, ios_base::beg); // 30 bytes beyond the beginning
fin.seekp(-1, ios_base::cur); // back up one byte
fin.seekp(0, ios_base::end); // go to the end of the file

注意:streampos和streampos是off_type和pos_type对于char类型的专门化;同样,针对wistream对象,wstreampos和streamoff类型是off_type和pos_type对于wistream类型的专门化。

4.9 fstream对象 or istream对象.tellg()

返回值为streampos,表示输入指针的当前文件位置(单位为字节),相对于文件开始的偏移量。

注意:如果创建了fstream对象,由于输入指针和输出指针将同时移动,因此tellg()和tellp()返回值相同;然而,如果使用istream对象来管理输入流,而使用ostream对象管理输出流,则输入指针和输出指针将彼此独立移动,tellg()和tellp()返回值将不同。

4.10 fstream对象 or ostream对象.tellp()

返回值为streampos,表示输出指针的当前文件位置(单位为字节),相对于文件开始的偏移量。

注意:如果创建了fstream对象,由于输入指针和输出指针将同时移动,因此tellg()和tellp()返回值相同;然而,如果使用istream对象来管理输入流,而使用ostream对象管理输出流,则输入指针和输出指针将彼此独立移动,tellg()和tellp()返回值将不同。

4.11 fstream对象 or ostream对象 or istream对象.seekg(偏移量)

将文件指针指向距离文件开头 偏移量(单位为字节) 大小的位置。

可以使用它将文件指针指向文件开头。

5 简单文件输入输出

5.1 写入到文本文件中

步骤:

  • 1 包含fstream头文件,fstream头文件中定义了ofstream类用于处理输出
  • 2 包含std命名空间(ofstream在std命名空间中)
  • 3 定义一个或多个ofstream对象,命名要求符合命名规范,每个ofstream对象都与一个输出流绑定在一起
  • 4 将对象和文件关联起来,方法之一是open()方法,这种关联在对象释放时自动解除
  • 5 文件操作完成时,应使用close()方法关闭文件
  • 6 可以使用ofstream对象和<<操作符输出各种类型的数据,可以使用cout可使用的任何方法(cout使用方法见C++ cout的用法,看这一篇就够了)

5.2 读取文本文件

步骤:

  • 1 包含fstream头文件,fstream头文件中定义了ifstream类用于处理输入,ifstream与一个输入流绑定在一起
  • 2 包含std命名空间(ifstream在std命名空间中)
  • 3 定义一个或多个ifstream对象,命名要求符合命名规范,每个ofstream对象都与一个输入流绑定在一起
  • 4 将对象和文件关联起来,方法之一是open()方法
  • 5 文件操作完成时,使用close()方法关闭文件
  • 6 可以使用ifstream对象和>>操作符输出各种类型的数据,可以使用cin可使用的任何方法(cin使用方法见C++ cin的用法,看这一篇就够了)
  • 7 ifstream本身作为测试条件时,如果最后一个读取操作成功,ifstream将被转换为true,否则转换为false

5.3 C++实例

5.3.1 cpp代码

/*
Project name :			_26File
Last modified Date:		2022年4月29日22点20分
Last Version:			V1.0
Descriptions:			简单文件输入输出
*/
#include <iostream>
#include <fstream> // for file I/O,这个头文件包含了iostream头文件,所以此处可以不显示包含iostream头文件
#include <cstdlib> // support for exit()
const int SIZE = 60;
int main()
{
   
	using namespace std;
	cout << "ofstream*********************************************************************" << endl;
	char automobile[50];
	int year;
	double a_price;
	double d_price;
	string filename1;
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jasmine-Lily

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值