C++把对文件的读写操作都封装在以下类中:
① ofstream 对文件的写操作 继承了ostream类的功能
② ifstream 对文件的读操作 继承了istream类的功能
③ fstream 对文件的读写操作 继承了ofstream\ifstream类
fstream( const char *filename, [openmode mode] );
ifstream( const char *filename, [openmode mode]);
ofstream( const char *filename, [openmode mode] );
void open( const char *filename );
void open( const char *filename, openmode mode );
mode:打开方式
ios::app 添加输出
ios::ate 当已打开时寻找到EOF
ios::binary 以二进制模式打开文件
ios::in 为读取打开文件
ios::out 为写入打开文件
ios::trunc 覆盖存在的文件
注意:
ifstream类 默认只读方式打开文件,文件不存在会失败 r
ofstream类 默认只写方式打开文件,文件存在则清空,不存在则创建 w
fstream类 默认读写方式打开文件,文件不存在失败 r+
if(!fin) // 失败
good() // 上一次文件操作没有错误,返回真
fail() // 上一次文件操作有错误,返回真
C++是借助流操作进行文本文件的读写
流对象 << 数据 // 写操作
流对象 >> 数据 // 读操作
void close();
注意:只是关闭流对象当前打开的文件,流对象并没有销毁,还可以后续继续直接使用
注意:在读写类对象时,由于绝大多数的成员变量都是private,因此无法直接在类外读写成员变量
a、实现public属性的get\set成员函数来访问私有成员,虽然可以个性化访问,但比较麻烦
b、由于ostream\istream分别是ofstream\ifstream的父类,因此如果重载这两个父类的 <<\>> 运算符,那么子类也会继承,所以重载输入输出运算符,既可以用于显示、输入对象,也可以具备通过运算符读写文件的效果,一举两得,更为便捷,但是格式相对较固定
C++为文件IO提供了两套操作位置指针的函数,只是为了兼容支持两个位置指针的系统,但是UNIX/Linux/Windows系统底层都只有一个读写共享的位置指针,因此使用哪套都可以
ostream &seekp( off_type offset,ios::seekdir origin);
功能:通过 基础位置+偏移值 设置写操作位置指针的位置
offset:偏移值
origin:基础位置
ios::beg 文件开头
ios::cur 当前位置
ios::end 末尾位置
istream &seekg( off_type offset,ios::seekdir origin);
功能:通过 基础位置+偏移值 设置读操作位置指针的位置
ostream &seekp( pos_type position );
功能:通过 绝对位置 设置写操作位置指针的位置
position:距离开头的字节数
istream &seekg( pos_type position );
功能:通过 绝对位置 设置读操作位置指针的位置
pos_type tellg();
功能:获取读操作位置指针的位置
pos_type tellp();
功能:获取写操作位置指针的位置
① 创建流对象、打开文件
注意:如果是Windows系统,mode打开方式需要增加 ios::binary 选项
② 判断文件是否打开成功
③ 读写操作
通过成员函数 read\write 来进行二进制读写
ostream &write(const char *buffer,streamsize num);
功能:以二进制写文件
buffer:待写入数据的内存首地址
num:要写入的字节数
istream &read( char *buffer, streamsize num );
功能:以二进制方式读文件
buffer:存储读取到的数据的内存首地址
num:要读取的字节数
注意:C++的write只有两种结果,要么num个字节全部写入成功,要么一个都每写入成功,因此通过good/fail判断上一次写入是否成功,所以不需要知道成功写入的个数[0\num]
streamsize gcount();
功能:获取上一次二进制读文件成功读取到的字节数
bool eof();
功能:判断文件流是否到达了文件末尾,如果是返回true
否则返回false
while(true)
{
fio.read();
if(fio.eof()) break;
// 执行读取成功后的相应操作
}
④ 关闭文件、销毁对象
注意:以二进制方式读写对象时,对象的成员不应该有指针类型(string),因为写入时只会把指针类型的对象存储的地址编号写入文件,而不会通过地址编号访问对应内存去写入,所以当后面重新读取文件时,读到的是之前写入的已经没有意义的地址编号,所以写入时需要深拷贝
a、更换对象中的指针成员 例如string换成char[]
b、通过深拷贝,把成员中指针指向的内存写入文件
C++中的typeid运算符可以获取数据的类型信息,需要添加头文件
① 运算符的结果是一个类对象
② 该对象中有一个name成员函数,可以返回数据的类型名
③ 该对象还重载了 == 运算符,可以判断两个数据类型是否相同(指针类型还会比较常属性)
④ 还可以区别某个父类指针或引用指向的是哪个子类对象,例如:Base* b = new Son1;
⑤ 不可以重载