C/C++文件读写(最全方法,多种实现)

您所在的位置:网站首页 大学未来规划100字左右 C/C++文件读写(最全方法,多种实现)

C/C++文件读写(最全方法,多种实现)

2023-07-25 21:36| 来源: 网络整理| 查看: 265

文章目录 前言一、文件处理过程二、C处理文件1.打开文件2.读文件4.写文件5.关闭文件 三、C++处理文件四、Windows API处理文件五、ATL处理文件总结

C/C++实战入门到精通 https://blog.csdn.net/weixin_50964512/article/details/125710864 前言

本章主要详解C/C++对文件的所有常见方法汇总

先要明白一个概念,即几乎在所有编程语言中,文件处理都是一个非常重要的模块

因为文件可以实现对数据大量且长久的存储

一、文件处理过程

无论什么编程语言,处理文件的过程都可以分为以下三步:

打开文件操作文件关闭文件

所以当我们操作文件的时候,请务必牢记这三点,因为该逻辑几乎是所有语言通用的,只不过具体实现细节略有差异

二、C处理文件

首先来看C中处理文件的方式,因为C是面向过程的语言,所以使用起来较为繁琐,你需要记住很多函数

而这些函数所在的头文件为:

#include //或者#include均可

同时需要注意的是:

C语言库中的函数,很多都存在安全隐患,就会存在一个相应的安全函数,一般对应的安全函数名称都是在原函数后添加_s后缀

例如:fopen的安全函数为fopen_s

相比较而言,安全函数会比标准函数使用更繁琐,所以很多情况下我们会习惯于使用标准函数,

但在VS环境下直接使用不安全的函数,会直接报错,编译无法通过,此时就必须要定义对应的宏才能正常使用

而安全函数则无需定义任何宏,可直接使用

具体使用哪一种看个人习惯,官方推荐使用安全函数

1.打开文件

首先是打开文件的函数:

//标准函数: FILE* fopen( const char * _FileName,//要打开的文件名,不指定路径,则在当前文件夹找 const char * _Mode //打开的模式 读r 写w 或追加a ); //返回值:打开失败返回NULL,打开成功则返回指向文件的标识符 //安全函数 errno_t fopen_s( FILE** _Stream, //保存打开文件后的标识符 const char * _FileName, //要打开的文件名,不指定路径,则在当前文件夹找 const char * _Mode //打开的模式 读r 写w 或追加a ); //返回值:打开成功返回0,打开失败则返回对应错误代码

两种函数的使用区别:

#define _CRT_SECURE_NO_WARNINGS //vs环境下,必须定义该宏,否则报错 #include using namespace std; int main() { FILE* file = fopen("1.txt","r"); //以读的方式打开文件 if (file == NULL) { //file为NULL,则打开文件失败,退出程序 return -1; } } #include using namespace std; int main() { FILE* file; errno_t err=fopen_s(&file,"1.txt","r"); //以读的方式打开文件 if (err != 0) { //err不为0,则打开文件失败,退出程序 return -1; } }

对于mode参数,有如下选择: 在这里插入图片描述

2.读文件

然后就是文件操作中的读:

//标准函数: size_t fread( void* _Buffer, //读取到的内容存放空间 size_t _ElementSize, //每次读多少个字节 size_t _ElementCount, //读多少次 FILE* _Stream //文件标识符 ); //返回值:实际读取的次数,注意,实际的取得字节数应该是该返回值和_ElementSize参数相乘,所以一般_ElementSize参数填1 //安全函数: size_t fread_s( void* _Buffer,//读取到的内容存放空间 size_t _BufferSize, //第一个参数指示的缓存区大小 size_t _ElementSize,//每次读多少个字节 size_t _ElementCount,//读多少次 FILE* _Stream //文件标识符 ); //返回值:实际读取的次数,注意,实际的取得字节数应该是该返回值和_ElementSize参数相乘,所以一般_ElementSize参数填1

两者使用区别:

#define _CRT_SECURE_NO_WARNINGS #include using namespace std; int main() { FILE* file = fopen("1.txt","r"); //以读的方式打开文件 if (file == NULL) { //file为NULL,则打开文件失败,退出程序 return -1; } char buf[0xFF]; //定义存放读取内容的缓存区 size_t size=fread(buf,1,100, file); //每次读一个字节,读100次 } #include using namespace std; int main() { FILE* file; errno_t err=fopen_s(&file,"1.txt","r"); //以读的方式打开文件 if (err != 0) { //err不为0,则打开文件失败,退出程序 return -1; } char buf[0xFF]; //定义存放读取内容的缓存区 size_t size=fread_s(buf,sizeof(buf),1,100,file);//每次读一个字节,读100次 }

除了上面最基本的读文件数据函数,还有一些其它读操作的函数:

fgetc:从文件中读取一个字符 int fgetc( FILE* _Stream //文件标识符 ); //返回值:返回读取到的一个字符 #define _CRT_SECURE_NO_WARNINGS //vs环境下必须定义该宏,否则报错 #include using namespace std; int main() { FILE* file = fopen("1.txt","r"); //已只读方式打开 if (file == NULL) { //打开失败直接返回 return -1; } char c=fgetc(file); //读取一个字符 } fgets:从文件中读取一个字符串 char* __cdecl fgets( char* _Buffer, //存放读到的字符缓冲区 int _MaxCount, //该缓存区的大小 FILE* _Stream //文件标识符 ); //返回值:成功为_Buffer指针,失败为NULL

使用:

#define _CRT_SECURE_NO_WARNINGS //vs环境下必须定义该宏,否则报错 #include using namespace std; int main() { FILE* file = fopen("1.txt","r"); //已只读方式打开 if (file == NULL) { //打开失败直接返回 return -1; } char buf[0xFF]; fgets(buf,0xFF,file); //读取一行字符串 } fscanf:按格式从文件中读取指定内容,与scanf函数类似 int fscanf( FILE* const _Stream,//文件标识符 char const* const _Format, //指定读取格式,与printf格式相同 ... //存放读取内容的缓存区 )

使用:

#define _CRT_SECURE_NO_WARNINGS //vs环境下必须定义该宏,否则报错 #include using namespace std; int main() { FILE* file = fopen("1.txt","r"); //已只读方式打开 if (file == NULL) { //打开失败直接返回 return -1; } int d; //存放数字 char buf[0xFF]; //存放字符串的缓存区 fscanf(file,"%d %s",&d,buf); //按格式读取文件内容 } fscanf_s:fscanf的安全函数,作用相同 int fscanf_s( FILE* const _Stream,//文件标识符 char const* const _Format, //指定读取格式,与printf格式相同 ... //存放读取内容的缓存区,注意在每个缓存区大小后一个参数为该缓存区的大小 )

使用:

#include using namespace std; int main() { FILE* file; errno_t err=fopen_s(&file,"1.txt","r"); if (err != 0) { return -1; } int b; char buf[0xFF]; fscanf_s(file,"%d %s",&b,buf,sizeof(buf)); fclose(file); } 4.写文件

文件操作主要就两个,上面说了读,下面就是写了:

标准函数:

size_t fwrite( void const* _Buffer, //要写入的内容 size_t _ElementSize, //元素大小 size_t _ElementCount, //元素个数 FILE* _Stream //文件标识 );

使用:

#define _CRT_SECURE_NO_WARNINGS //vs环境下必须定义该宏,否则报错 #include using namespace std; int main() { FILE* file = fopen("1.txt","w"); //已只读方式打开 if (file == NULL) { //打开失败直接返回 return -1; } char buf[] = "test"; //要写入的内容 fwrite(buf,1,sizeof(buf),file); //写入操作 }

该函数无安全函数

除了最基本的写入函数,还有一些其它的常用写操作函数:

fputc:向文件中写入一个字符 int fputc( int _Character,//要写入的字符 FILE* _Stream //文件标识符 );

使用:

#include using namespace std; int main() { FILE* file; errno_t err=fopen_s(&file,"1.txt","w"); if (err != 0) { return -1; } int ret=fputc('c',file);//向file标识的文件写入一个c字符 } fputs:向文件中写入一个字符串 int fputs( char const* _Buffer,//要写入的内容 FILE* _Stream //文件标识符 );

使用:

int main() { FILE* file; errno_t err=fopen_s(&file,"1.txt","w"); if (err != 0) { return -1; } char buf[] = "test"; int ret = fputs(buf,file); //将buf内的内容写入到file标识的文件 } fprintf:向文件中写入指定格式字符串,与pritnf函数类似 int fprintf( FILE* _Stream, //文件标识符 char const* const _Format, //写入格式 与printf使用方式相同 ... )

使用:

#include using namespace std; int main() { FILE* file; errno_t err=fopen_s(&file,"1.txt","w"); if (err != 0) { return -1; } fprintf(file,"%d %s",4,"test"); //向fille标识的文件写入数字4和字符串test } fprintf_s:fprintf的安全函数

与fprintf没什么区别,不再讲解

5.关闭文件

最后是关闭文件

int fclose( FILE* _Stream //文件标识符 );

使用:

#include using namespace std; int main() { FILE* file; errno_t err=fopen_s(&file,"1.txt","w"); if (err != 0) { return -1; } fclose(file);//关闭文件 } 三、C++处理文件

C++使用了面向对象对文件处理进行了封装,所以处理文件会比C方便很多

为了方便使用,C++封装了三个文件操作类

头文件:

#include //处理文件的头文件 using namespace std; //引用该命名空间,不引用将必须使用std::fstring 的方式使用该类

代码:

首先是最通用的类fstream:

#include using namespace std; int main() { fstream file; file.open("1.txt",ios::out); //以只写模式打开文件 char buf[] = "test"; file.write(buf,sizeof(buf));//写入文件 file.close(); //关闭文件 file.open("1.txt", ios::app); //以追加模式打开文件 char buf1[] = "test1"; file.write(buf1, sizeof(buf));//写入文件末尾 file.close(); //关闭文件 file.open("1.txt",ios::in); //以只读方式打开文件 char buf2[0xFF]; //存储读取的内容 file.read(buf2,0xFF); //读文件 file.close(); //关闭文件 }

模式选择: 在这里插入图片描述 但既然已经封装成为了类,那么在特定需求下,打开文件这个操作也是可以省略的

首先是读文件的类ifstream:

#include #include using namespace std; int main() { ifstream f("1.txt"); char buf[0xFF]; f.read(buf,0xFF); //普通读取 char c=f.get(); //读取一个字符 char bufLine[0xFF]; f.getline(bufLine,0xFF); //读取一行 }

然后是写文件的类ofstream:

#include #include using namespace std; int main() { ofstream f("1.txt"); char buf[0xFF]; f.write("hello world",12); //普通写 f.put('c'); //写入一个字符 } 四、Windows API处理文件

如果是在windows系统,那么还可以直接调用系统api完成文件读写操作

但会更加复杂

需要头文件:

#include

首先是打开文件的函数:CreateFileA或CreateFileW

HANDLE CreateFileA( LPCSTR lpFileName, //要打开的文件名 DWORD dwDesiredAccess, //访问文件权限 DWORD dwShareMode, //文件共享模式 LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全模式,一般填0,默认 DWORD dwCreationDisposition, //打开方式 DWORD dwFlagsAndAttributes, //打开文件的属性和标志,一般为FILE_ATTRIBUTE_NORMAL HANDLE hTemplateFile //模板文件句柄,一般为NULL );

然后读文件函数:ReadFile

BOOL ReadFile( HANDLE hFile, //要读取的文件句柄,CreateFileA的返回值,相当于c中的FILE LPVOID lpBuffer, //存储读取内容的缓存区 DWORD nNumberOfBytesToRead, //要读取的字节数 LPDWORD lpNumberOfBytesRead, //接收读到的字节数 LPOVERLAPPED lpOverlapped //重叠结构,一般填NULL );

还有写文件函数:WriteFile

BOOL WriteFile( HANDLE hFile,//要写入的文件句柄,CreateFileA的返回值,相当于c中的FILE LPCVOID lpBuffer,//要写入文件的缓存区 DWORD nNumberOfBytesToWrite, //要写入的字节数 LPDWORD lpNumberOfBytesWritten, //接收已经写入的字节数 LPOVERLAPPED lpOverlapped //重叠结构,一般填NULL );

最后是关闭文件函数:CloseHandle

BOOL CloseHandle( HANDLE hObject //要关闭的文件句柄 );

示例:

#include int main() { HANDLE hFile=CreateFileA("1.txt", GENERIC_READ | GENERIC_WRITE,0,0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); //打开读写模式打开文件 if (hFile == NULL) { //打开文件失败,退出 return -1; } DWORD len; WriteFile(hFile,"test",sizeof("test"),&len,NULL); //写文件 char buf[0xFF]; ReadFile(hFile,buf,0xFF,&len,NULL); //读文件 CloseHandle(hFile);//关闭文件 } 五、ATL处理文件

如果你觉得直接使用win API操作文件太麻烦,那就可以尝试自己将其封装一个类

而ATL就帮我们把这一个工作给做了,在VS环境下,可以直接包含这个头文件:

#include

该头文件中有一个CAtlFile类,就是简洁的将上面的win API函数封装了一下

其使用方式比win API会简洁很多

#include int main() { CAtlFile file; file.Create(L"text.txt", GENERIC_ALL, 0, CREATE_NEW); char buf[20] = "hello world"; file.Write(buf, 20); file.Read(buf, 20); file.Close(); }

正如你所看到的,它仅仅只是简单的封装了一下,其参数依旧是win API对应的参数,需要经常查询文档

其优点就是提高了我们的开发速度,而且最终生成的目标程序与直接使用win API进行开发相差不大

总结

如果你希望提高开发速度,跨平台,那么我推荐你使用C++方式

如果在意目标程序的大小,但想要跨平台,那么我推荐你使用C方式

如果你只是想要在windows平台开发程序,很在意程序的大小,那么我就推荐你使用win API

在此基础上如果你还想要提高开发速度,那么就可以使用一下ATL里面封装好的文件类

想要深入学习C/C++的同学,可以点击下方链接查看一份详细的C/C++教程,以项目为主导,从入门到精通!

C/C++实战入门到精通 https://blog.csdn.net/weixin_50964512/article/details/125710864


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3