C++之文件读写
一、C++ I/O流
头文件:fstream
C++把对文件的读写操作都封装在以下的类中:
类名 | 功能 | 继承 | 相当于 |
---|---|---|---|
ofstream | 对文件的写操作,默认以只写方式O_WRONLY|O_CREAT|O_TRUNC打开文件,文件不存在则创建、存在则清空 | ostream类 | "w" |
ifstream | ifstream类 对文件的读操作,默认以只读方式O_RDONLY打开文件,文件不存在则失败 | istream类 | "r" |
fstream | 对文件读写操作,默认以读写方式O_RDWR打开文件,文件不存在则失败,文件存在不清空 | ofstream类、ifstream类 | "r+" |
二、C++对文本文件的读写
-
创建流对象,通过流对象打开文件
①ofstream ofs(const char *filename, openmode mode );
②通过成员函数方式,打开文件
void open( const char *filename ); void open( const char *filename, openmode mode ); filename:文件的路径 mode: 打开方式 ios::app 添加输出 ios::ate 当已打开时寻找到EOF ios::binary 以二进制模式打开文件 ios::in 为读取打开文件 ios::out 为写入打开文件 ios::trunc 覆盖存在的文件
注意:ios::里面打开模式单独使用和混合使用时候有些功能会有所删减变化,不是简单的功能相加,具体底层调用哪个打开模式可以通过 strace ./a.out 来追踪底层对系统函数的调用
-
如何判断文件是否打开成功
-
通过 !流对象名 执行了该类的!运算符重载版本
if(!ifs) // 为真 失败
-
通过good\fail成员函数判断是否成功
bool good(); 功能:判断上一次流操作是否成功,成功返回真,一般用于判断文件是否打开成功
-
-
读写文件
①流对象 << 写操作
②流对象 >> 读操作 -
关闭文件
成员函数:void close(void)
注意:只是关闭流对象当前的文件,但是流对象没有销毁,还可以继续通过open成员函数重新打开别的文件
-
如何以文本方式读写类对象?
-
读写类对象时绝大部分成员变量都是私有的,因此无法直接在类外进行读写
-
由于ostream/istream分别是ofstream/ifstream的父类,因此如果重载了>> <<运算符,既可以用于平时输出、输入类对象,并且还可以直接用于类对象的文本方式流操作读写
cout << 类对象
cin >> 类对象 重载后
ofs << 类对象
ifs >> 类对象 成立
-
三、C++的随机读写
C++为文件IO流提供了两套设置位置指针的成员函数,为了兼容一些有两个位置指针的操作系统,但是UNIX、Linux、Windows系统底层只有一个文件位置指针,所以使用哪套都没区别
istream &seekg( off_type offset, ios::seekdir origin );
功能:通过 偏移量+基础位置 设置位置指针的位置
offset:偏移量
origin:基础位置
ios::beg 文件开头
ios::cur 当前位置
ios::end 文件末尾
istream &seekg( pos_type position );
功能:通过绝对值的方式设置位置指针的位置
seekp 功能类似
pos_type tellp();
功能:获取位置指针所在文件的绝对位置
tellg功能类似
四、C++对二进制文本的读写
-
创建流对象、打开文件
ios::binary 以二进制模式打开文件 -
读写操作
ostream &write(const char *buffer,streamsize num); 功能:以二进制方式写文件 buffer:待写入数据的内存首地址 num:待写入的字节数
注意:C++的write只会有两种结果,要么num个字节全部写入,要么一个都没写入,可以通过good、fail判断上一次的写操作是否成功
istream &read( char *buffer, streamsize num ); 功能:以二进制方式读文件 buffer:存储读取到的数据的内存首地址 num:要读取的字节数
streamsize gcount(); 功能:获取上一次读操作中成功读取到的字节数
bool eof(); 功能:判断读操作是否读到了文件末尾,如果是返回真
-
二进制读写需要注意的问题:
-
对象的成员变量中不应该有指针类型(或string类型),因为此时写入时只会把指针变量存储的地址写入,而下次读取到该指针变量时,该指针地址已经没有意义了
-
一直读取二进制文件
while(true) { // 读操作 if(fs.eof()) break; // 读成功,执行相应操作 }
-
作业:使用C++实现一个mv带覆盖检查的命令
#include <iostream>
#include <unistd.h>
#include <fstream>
using namespace std;
int main(int argc,const char* argv[])
{
if(3 != argc)
{
cout << "User: ./MV <src> <dest>" << endl;
return -1;
}
ifstream ifs(argv[1]);
if(!ifs)
{
cout << "原文件不存在,请检查!" << endl;
return -1;
}
if(0 == access(argv[2],F_OK))
{
cout << "目标文件已存在,是否覆盖(y/n)?" << endl;
char cmd;
cin >> cmd;
if('y' != cmd)
{
cout << "停止移动!" << endl;
ifs.close();
return 0;
}
}
ofstream ofs(argv[2]);
if(!ofs)
{
cout << "目标位置无权限,请检查!" << endl;
ifs.close();
return -1;
}
char buf[4096] = {};
while(true)
{
ifs.read(buf,sizeof(buf));
if(ifs.eof()) break;
ofs.write(buf,ifs.gcount());
}
ifs.close();
ofs.close();
unlink(argv[1]);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!