C/C++ file reading and writing (the most comprehensive method, multiple implementations)

From entry to mastery of C/C++ combat https://blog.csdn.net/weixin_50964512/article/details/125710864

foreword

This chapter mainly explains in detail the summary of all common methods of C/C++ on files

First of all, we must understand a concept, that is, in almost all programming languages, file processing is a very important module

Because files can realize large and long-term storage of data

1. Document processing process

No matter what programming language, the process of processing files can be divided into the following three steps:

  1. open a file
  2. operation file
  3. close file

So when we operate files, please keep these three points in mind, because the logic is common to almost all languages, but the specific implementation details are slightly different

Two, C processing files

First, let’s look at the way of processing files in C, because C is a process-oriented language, so it is more cumbersome to use, and you need to remember a lot of functions

The header files where these functions are located are:

#include<cstdio> //或者#include<stdio.h>均可

At the same time, it should be noted that:

Many functions in the C language library have security risks, and there will be a corresponding security function. Generally, the name of the corresponding security function is suffixed after the original function _s.

For example: fopenthe security function offopen_s

In comparison, security functions are more cumbersome to use than standard functions, so in many cases we will get used to using standard functions,

However, if you use an unsafe function directly in the VS environment, an error will be reported directly, and the compilation will not pass. At this time, you must define the corresponding macro to use it normally.

The safe function does not need to define any macros and can be used directly

Which one to use depends on personal habits, the official recommendation is to use the security function

1. Open the file

First is the function to open the file:

//标准函数:
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,打开失败则返回对应错误代码

The difference between the two functions:

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

For modeparameters, the following options are available:
insert image description here

2. Read the file

Then there is the read in the file operation:

//标准函数:
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

The difference between the two uses:

#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
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<cstdio>
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次
}

In addition to the most basic functions for reading file data above, there are some other functions for reading operations:

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

use:

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

use:

#define _CRT_SECURE_NO_WARNINGS //vs环境下必须定义该宏,否则报错
#include<cstdio>
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); //按格式读取文件内容
}
  1. fscanf_s: fscanfthe security function of
int fscanf_s(
 FILE*       const _Stream,//文件标识符
 char const* const _Format, //指定读取格式,与printf格式相同
        ... //存放读取内容的缓存区,注意在每个缓存区大小后一个参数为该缓存区的大小
)

use:

#include<cstdio>
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. Write files

There are mainly two file operations, the above is to read, and the following is to write:

Standard functions:

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

use:

#define _CRT_SECURE_NO_WARNINGS //vs环境下必须定义该宏,否则报错
#include<cstdio>
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); //写入操作
}

This function has no security function

In addition to the most basic write function, there are some other commonly used write operation functions:

  1. fputc: write a character to the file
int  fputc(
int   _Character,//要写入的字符
FILE* _Stream //文件标识符
);

use:

#include<cstdio>
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字符
}
  1. fputs: write a string to the file
int fputs(
char const* _Buffer,//要写入的内容
FILE* _Stream //文件标识符
);

use:

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标识的文件
}

  1. fprintf: Write the specified format string to the file, pritnfsimilar to the function
int fprintf(
 FILE* _Stream, //文件标识符
char const* const _Format, //写入格式 与printf使用方式相同
        ...
)

use:

#include<cstdio>
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
}
  1. fprintf_s: fprintfthe security function of

There is no difference with it fprintf, no more explanation

5. Close the file

Finally close the file

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

use:

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

3. C++ processing files

C++ uses object-oriented packaging for file processing, so file processing is much more convenient than C

For ease of use, C++ encapsulates three file operation classes

head File:

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

code:

First the most general class fstream:

#include<fstream>
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(); //关闭文件
}

Mode selection:
insert image description here
But since it has been encapsulated into a class, the operation of opening the file can also be omitted under specific requirements

The first is the class that reads the file ifstream:

#include<iostream>
#include<fstream>
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); //读取一行
}

Then there is the class that writes the file ofstream:

#include<iostream>
#include<fstream>
using namespace std;
int main() {
    
    
	ofstream f("1.txt");
	char buf[0xFF];
	f.write("hello world",12); //普通写
	f.put('c'); //写入一个字符
}

4. Windows API processing files

If it is in the windows system, you can also directly call the system api to complete the file read and write operations

but it will be more complicated

Header files are required:

#include<Windows.h>

The first is the function to open the file: CreateFileA or CreateFileW

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

Then read the file function: ReadFile

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

There is also a file writing function: WriteFile

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

Finally, close the file function: CloseHandle

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

Example:

#include<Windows.h>
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);//关闭文件
}

5. ATL processing files

If you think it is too troublesome to directly use the win API to manipulate files, you can try to encapsulate a class yourself

And ATL helps us do this work. In the VS environment, you can directly include this header file:

#include<atlfile.h>

There is a class in the header file CAtlFile, which simply encapsulates the above win API function

Its usage is much simpler than win API

#include<atlfile.h>
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();
}

As you can see, it is simply encapsulated, and its parameters are still the parameters corresponding to the win API, so you need to check the documentation frequently

The advantage is that our development speed is improved, and the final target program is not much different from the direct use of win API for development.

Summarize

If you want to improve development speed and cross-platform, then I recommend you to use C++

If you care about the size of the target program, but want to cross-platform, then I recommend you use the C method

If you just want to develop programs on the windows platform and care about the size of the program, then I recommend you to use the win API

On this basis, if you still want to improve the development speed, then you can use the packaged file class in ATL

Students who want to learn C/C++ in depth can click the link below to view a detailed C/C++ tutorial, which is project-oriented, from entry to mastery!

From entry to mastery of C/C++ combat https://blog.csdn.net/weixin_50964512/article/details/125710864

Guess you like

Origin blog.csdn.net/weixin_50964512/article/details/123240393