The Road to C Language Learning (Basics) - File Operation (Part 1)

Note: This blog is written word by word by the blogger, which is not easy. Please respect the originality, thank you all!

Overview

1) Disk files and device files

  • Disk file
    refers to a set of ordered collections of related data, usually stored on external media (such as disks) and loaded into memory only when used.

  • Device file
    In the operating system, each input and output device connected to the host is regarded as a file, and their input and output are equivalent to reading the disk file. and write.

2) Classification of disk files

Computer storage is physically binary, so physically all disk files are essentially the same: sequential storage in bytes.

Insert image description here
From the perspective of user or operating system usage (logically), files are divided into:

  • Text file: Character encoding based file
  • Binary file: Value-based encoding

3) Text files and binary files

3.1 Text files

  • is based on character encoding. Common encodings include ASCII, UNICODE, etc.
  • Generally, you can use a text editor to open it directly.
  • The storage form (ASCII code) of number5678 in ASCII is: (first convert 5678 to a> 00110101 00110110 00110111 00111000, and then converted to binary)ASCIIcode value53、54、55、56

3.2 Binary files

  • Based on value coding, you can specify what a certain value means based on the specific application.
  • Output the data in the memory to the disk as it is stored in the memory
  • The storage form (binary code) of number5678 is:
  • 00010110 00101110

Opening and closing files

1) File pointer

InC language, a pointer variable is used to point to a file. This pointer is called a file pointer.

typedef struct
{
    
    
	short           level;	//缓冲区"满"或者"空"的程度 
	unsigned        flags;	//文件状态标志 
	char            fd;		//文件描述符
	unsigned char   hold;	//如无缓冲区不读取字符
	short           bsize;	//缓冲区的大小
	unsigned char   *buffer;//数据缓冲区的位置 
	unsigned        ar;	 //指针,当前的指向 
	unsigned        istemp;	//临时文件,指示器
	short           token;	//用于有效性的检查 
}FILE;

FILE is a structure type of file information defined by the system using typedef. The structure contains information such as file name, file status and current location of the file.

DeclarationFILEThe information of the structure type is included in the header file"stdio.h", generally setting a pointer to the FILE type variable pointer variables, and then reference theseFILE type variables through it. Through the file pointer, various operations can be performed on the file it points to.
Insert image description here
CThere are three special file pointers in the language that are opened by the system by default and can be used directly by users without defining them:

  • stdin: standard input, defaults to the current terminal (keyboard), we use the scanf, getchar functions Data is obtained from this terminal by default.
  • stdout: standard output, defaults to the current terminal (screen), we use the printf, puts functions Information is output to this terminal by default.
  • stderr: Standard error, defaults to the current terminal (screen), and the perror function we use defaults to output information to this terminal.

Insert image description here

2) Opening the file

Any file must be opened before use:

  • Header file:#include <stdio.h>
  • Define function:FILE * fopen(const char * filename, const char * mode);
  • Function: open file
  • Parameters:
    filename:The name of the file to be opened, plus the path as needed
    mode:The mode setting for opening the file
  • Return value:
    Success: file pointer
    Failure:NULL

Several forms of the first parameter:

FILE *fp_passwd = NULL;

//相对路径:
//打开当前目录passdw文件:源文件(源程序)所在目录
FILE *fp_passwd = fopen("passwd.txt", "r");

//打开当前目录(test)下passwd.txt文件
fp_passwd = fopen("./test/passwd.txt", "r");

//打开当前目录上一级目录(相对当前目录)passwd.txt文件
fp_passwd = fopen("../passwd.txt", "r");
	
//绝对路径:
//打开C盘test目录下一个叫passwd.txt文件
fp_passwd = fopen("c:/test/passwd.txt","r");

Several forms of the second parameter (how to open the file):

open mode meaning
rorrb Open a text file in read-only mode (does not create the file, and reports an error if the file does not exist)
worwb Open the file for writing (clear the file if it exists, create a file if it does not exist)
aorab Open the file in append mode, add content at the end, or create the file if it does not exist
r+orrb+ Open the file for reading and writing (does not create a new file)
w+orwb+ Open the file in a readable and writable manner (clear the file if it exists, create a file if it does not exist)
a+orab+ Open the file in add mode, open the file and change the file at the end, create the file if it does not exist

Notice:

  • b means binary mode. b is only valid in Windows and used in Linux. rThe result is the same asrb
  • UnixAll text file lines under and Linux end with \n, and all text file lines under Windows is\r\nend
  • presentWindowsunder the flat table, hereafter text ”< /span>b: Method opening statement, no addition
  • When reading the file, the system will convert all "\r\n" into "\n"
  • When writing to a file, the system will convert "\n" into "\r\n" for writing
  • Open the file in binary mode, then Neither reading nor writing will perform such conversion
  • inUnix/Linuxunder the flat table, text ” Production and character code original code input and output model free zone separation ,“ two-way system give \r\n

Example 1: Open a text file in read-only mode (do not create the file, and report an error if the file does not exist)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


int main()
{
    
    	
	//打开一个文件,成功返回FILE结构体地址,失败返回NULL
	// 返回的文件流指针标识了打开的那个文件
	FILE* fp = fopen("hello.txt", "r"); // 只读,不创建文件,若文件不存在则报错
	if (NULL == fp)
	{
    
    
		perror("open error");
		return;
	}


	return 0;
}
输出结果
open error: No such file or directory

Example 2: Open the file for writing (clear the file if it exists, create a file if it does not exist)

FILE* fp = fopen("hello.txt", "w"); // 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
if (NULL == fp)
{
    
    
	perror("open error");
	return;
}

Insert image description here

Edit the"hello.txt" file, fill in the data and save it. If the code is executed again, the file content will be cleared

3) Closing of files

Any file should be closed after use:

  • Open files will occupy memory resources. If they are always opened and not closed, a lot of memory will be consumed.

  • The number of files a process can open at the same time is limited. If the maximum number of files opened at the same time is exceeded, calling againfopento open the file will fail

  • If there is no explicit callfclose to close the open file, the operating system will be shut down when the program exits.

  • Header file:#include <stdio.h>

  • Define function:int fclose(FILE * stream);

  • Function: Close the file previously opened by fopen(). This action writes the buffer data to the file and releases the file resources provided by the system.

  • Parameter:
    stream:File pointer

  • Reply:
    Success:0
    Failure:-1

FILE* fp = fopen("hello.txt", "w"); // 以写方式打开文件(如果文件存在则清空文件,文件不存在则创建一个文件)
if (NULL == fp)
{
    
    
	perror("open error");
	return -1;
}
fclose(fp);

Sequential reading and writing of files

1) Read and write files fgetc and fputc according to characters

1.1 Write files

  • Header file:#include <stdio.h>
  • Define function:int fputc(int ch, FILE * stream);
  • Function: Convertch tounsigned char and then write it to the file specified by stream
  • Parameters:
    ch:Characters to be written to the file
    stream:File pointer
  • Return value:
    Success: Characters successfully written to the file
    Failure: Return-1

Example 1:Clear write

FILE* fp = fopen("hello.txt", "w"); 
fputc('a', fp);
fclose(fp);

Example 2:Additional transcription

FILE* fp = fopen("hello.txt", "a"); 
fputc('b', fp);
fclose(fp);

Example 3:Clear loop writing

FILE* fp = fopen("hello.txt", "w"); 
char buf[] = "this is a test for fputc";
int i = 0;
int n = strlen(buf);
for (i = 0; i < n; i++)
{
    
    
	//往文件fp写入字符buf[i]
	int ch = fputc(buf[i], fp);
	printf("ch = %c\n", ch);
}
fclose(fp);

Insert image description here

1.2 Reading files

  • Header file:#include <stdio.h>
  • Define function:int fgetc(FILE * stream);
    Function: Read a character from the file specified by Parameters: stream a> Failure: < /span> Success: Return the character read Return value: File pointer

    stream:


    -1

Example:Read the contents of the file

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


int main()
{
    
    
	FILE* fp = fopen("hello.txt", "r");
	char buf[128] = "";
	int i = 0;
	while ((buf[i++] = fgetc(fp)) != -1);
	printf("%s\n", buf);
	return 0;
}

Insert image description here

1.3 End of file

In C languages, EOF represents the end-of-file character (end of file). In the while loop, EOF is used as the end of file mark, and in , EOF is used as the file The file with the end mark must be a text file. In text files, data are stored in the form of character ASCII code values. We know that the range of ASCII code value is 0~127, and -1 is impossible, so we can use EOFAs the end of file mark.

#define EOF     (-1)

Example:UseEOF as the terminator, problems

// 写入-1
FILE* fp = fopen("hello.txt", "w");
if (NULL == fp)
{
    
    
	perror("open error");
	return -1;
}
char buf[10] = {
    
    97,-1,-2,98,99};
int i = 0;
while (buf[i] != 0)
{
    
    
	fputc(buf[i], fp);
	i++;
}
fclose(fp);

Insert image description here

int main()
{
    
    	
	FILE* fp = fopen("hello.txt", "r");
	char buf[128] = "";
	int i = 0;
	while ((buf[i++] = fgetc(fp)) != EOF);
	printf("%s\n", buf);
	return 0;
}

Insert image description here

When storing data in binary form into a file, the value -1 will appear, so EOF cannot be used as the end of the binary file. logo. To solve this problem, ANSI C provides a feof function to determine whether the file ends. The feof function can be used to judge both binary files and text files.

  • Header file:#include <stdio.h>
  • Define function:int feof(FILE * stream);
  • Function: Detect whether the end of the file has been read. What is judged is the content of the last " read operation " , not the current Location content (previous content).
  • Parameter:
    stream:File pointer
  • Return value:
    Not0Value: The end of the file has been reached
    0:The end of the file has not been reached

Example:Usefeof function to determine whether the file ends

int main()
{
    
    	
	FILE* fp = fopen("hello.txt", "r");
	char buf[128] = "";
	int i = 0;
	do
	{
    
    
		buf[i++] = fgetc(fp);
	} while (!feof(fp));
	
	printf("%s\n", buf);
	return 0;
}

Insert image description here

1.4 Intensive training: implement cp and cat commands

Case 1:Copy text file

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


void copyFile(char srcFileName[128], char dstFileName[128])
{
    
    
	// 打开src文件 创建dst文件
	FILE* fpread = fopen(srcFileName, "r");
	FILE* fpwrite = fopen(dstFileName, "w");
	if (NULL == fpread || NULL == fpwrite)
	{
    
    
		perror("open error");
		return -1;
	}
	while (1)
	{
    
    	
		int ch;
		//  读取src一个字符
		ch = fgetc(fpread);
		if (feof(fpread))
			break;
		// 写入到dst文件
		fputc(ch, fpwrite);

	}
	//关闭
	fclose(fpread);
	fclose(fpwrite);
}

int main()
{
    
    	
	char srcFileName[128] = "hello.txt";
	char dstFileName[128] = "hello2.txt";
	copyFile(srcFileName, dstFileName);

	return 0;
}

Insert image description here

Case 2:Copy image files

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


void copyFile(char srcFileName[128], char dstFileName[128])
{
    
    
	// 打开src文件 创建dst文件
	FILE* fpread = fopen(srcFileName, "rb"); 
	FILE* fpwrite = fopen(dstFileName, "wb");
	if (NULL == fpread || NULL == fpwrite)
	{
    
    
		perror("open error");
		return -1;
	}
	while (1)
	{
    
    	
		int ch;
		//  读取src文件
		ch = fgetc(fpread);
		if (feof(fpread))
			break;
		// 写入到dst文件
		fputc(ch, fpwrite);

	}
	//关闭
	fclose(fpread);
	fclose(fpwrite);
}

int main()
{
    
    	
	char srcFileName[128] = "csdn_cdtaogang_blog.png";
	char dstFileName[128] = "my_csdn_blog.png"; 
	copyFile(srcFileName, dstFileName);

	return 0;
}

Insert image description here

Case 3:Implement thecat command and output the file content to the terminal

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


int main()
{
    
    
	// 打开文件
	FILE *fpread = fopen("04拷贝案例.c", "r");
	if (NULL == fpread)
	{
    
    
		perror("open error");
		return -1;
	}
	// 读取文件
	int ch;
	while (1)
	{
    
    
		ch = fgetc(fpread);
		if (feof(fpread))
			break;
		fputc(ch, stdout);  //输出到终端
		
	}
	fclose(fpread);

	return 0;
}

Insert image description here

2) Read and write files fgets and fputs according to the line

2.1 Write files

  • Header file:#include <stdio.h>
  • Define function:int fputs(const char * str, FILE * stream);
    Function: Write the string specified by str into the file specified by stream , the string terminator'\0' is not written to the file.
  • Parameters:
    str:String
    stream:File pointer
  • Reply:
    Success:0
    Failure:-1

Example 1:Write a string to a file

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


int main()
{
    
    
	// 打开文件
	FILE *fpread = fopen("a.txt", "w");
	if (NULL == fpread)
	{
    
    	
		perror("open error");
		return -1;
	}
	// 写入字符串
	char buf[] = "hellocdtaogang";
	fputs(buf, fpread);

	return 0;
}

Insert image description here

Example 2:Write data to the file line by line, end writing when encountering\0, encounter\nJust wrap

int main()
{
    
    
	// 打开文件
	FILE *fpread = fopen("a.txt", "w");
	if (NULL == fpread)
	{
    
    	
		perror("open error");
		return -1;
	}
	// 写入字符串,遇到\0就结束
	char buf[] = "hello\0cdtaogang";
	fputs(buf, fpread);

	return 0;
}

Insert image description here

int main()
{
    
    
	// 打开文件
	FILE *fpread = fopen("a.txt", "w");
	if (NULL == fpread)
	{
    
    	
		perror("open error");
		return -1;
	}
	// 写入字符串,遇到\0就结束,遇到\n就换行
	//char buf[] = "hello\0cdtaogang";
	char buf[] = "hello\ncdtaogang";
	fputs(buf, fpread);

	return 0;
}

Insert image description here

2.2 Reading files

  • Header file:#include <stdio.h>
  • Define function:char * fgets(char * str, int size, FILE * stream);
  • Function: Read characters from the file specified bystream and save them to the memory space specified bystr until a newline character appears and the file is read. At the end or until size - 1 characters have been read, characters '\0' will be automatically added at the end to end the string.
  • Parameter:
    str:String
    size:Specifies the maximum length of the read string (size - 1)
    stream:File pointer
  • Return value:
    Success: successfully read string
    End of file read or error: NULL

Example 1:Read a string from a file

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>


int main()
{
    
    
	// 打开文件
	FILE* fpread = fopen("a.txt", "r");
	if (NULL == fpread)
	{
    
    
		perror("open error");
		return -1;
	}
	char buf[1024] = "";
	// 读取文件
	fgets(buf, sizeof(buf), fpread);
	printf("%s", buf);

	fclose(fpread);
	return 0;
}

Insert image description here

Example 2:Read a string from the file and end when it encounters\n

Insert image description here

Example 3:Use fgets and fputs to complete the copy of the text file (Binary file image reading cannot be used because string binary files have many 0s. fgets stops reading when it encounters 0. The same goes for fputs when writing files, so they can only operate text files< a i=5>)

int main()
{
    
    
	// 打开a文件 创建b文件
	FILE* fpread = fopen("a.txt", "r");
	FILE* fpwrite = fopen("b.txt", "w");
	if (NULL == fpread || NULL == fpwrite)
	{
    
    
		perror("open error");
		return -1;
	}
	char buf[128] = "";
	char* p = NULL;
	while (1)
	{
    
    
		//  读取a文件
		p = fgets(buf, sizeof(buf), fpread);
		if (NULL == p)
			break;
		// 写入到b文件
		fputs(buf, fpwrite);
	}
	//关闭
	fclose(fpread);
	fclose(fpwrite);

	return 0;
}

Insert image description here

2.3 Intensive training: file version of four arithmetic operations

There is a file of uncertain size. Each line contains a four-arithmetic expression. The result has not yet been calculated. Write a program to automatically calculate the result and then modify the file.
Insert image description here

Step one: Randomly generate10个 four arithmetic expressions and write them to the file.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define CALC_NUM 10  // 要生成四则运算表达式的个数


// 获取10个四则运算表达式并写入到文件中
void write_data()
{
    
    	
	// 生成并打开calc.txt文件
	FILE* fp = fopen("calc.txt", "w");
	if (NULL == fp)
	{
    
    
		perror("open error");
		return -1;
	}
	// 设置随机种子
	srand(time(NULL));
	// 定义基本运算符数组
	char ysf[] = {
    
     '+', '-', '*', '/' };
	int a, b = 0;
	char c = 0;
	// 定义一个buf数组来保存四则运算表达式
	char buf[128] = "";
	for (int i = 0; i < CALC_NUM; i++)
	{
    
    
		// 产生随机数1~100
		int a = rand() % 100 + 1;
		int b = rand() % 100 + 1;
		// 随机产生0~3的数
		int c = rand() % 4;  // 0,1,2,3  对应运算符数组下标
		// 组包
		sprintf(buf, "%d%c%d=\n", a, ysf[c], b);
		printf(buf);
		// 写入到calc.txt文件中
		fputs(buf, fp);
	}
	// 关闭文件
	fclose(fp);
}

int main()
{
    
    	
	// 调用
	write_data();

	return 0;
}

Insert image description here

Step 2: Readcalc.txtRead the contents of the file line by line, unpack the calculation results after reading them once, and then package the results into expressions< /span>

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define CALC_NUM 10  // 要生成四则运算表达式的个数
#define FILE_PATH "calc.txt"  // 文件路径


// 封装打开文件方法
FILE* open_file(char* str)
{
    
    
	
	FILE* fp = fopen(FILE_PATH, str);
	if (NULL == fp)
	{
    
    
		perror("open error");
		return -1;
	}
	return fp;
}

// 封装关闭文件方法
void close_file(FILE* fp)
{
    
    
	fclose(fp);
	return;
}

// 获取10个四则运算表达式并写入到文件中
void write_data()
{
    
    	
	// 生成并打开calc.txt文件
	FILE* fp = open_file("w");
	// 设置随机种子
	srand(time(NULL));
	// 定义基本运算符数组
	char ysf[] = {
    
     '+', '-', '*', '/' };
	int a, b = 0;
	char c = 0;
	// 定义一个buf数组来保存四则运算表达式
	char buf[128] = "";
	for (int i = 0; i < CALC_NUM; i++)
	{
    
    
		// 产生随机数1~100
		int a = rand() % 100 + 1;
		int b = rand() % 100 + 1;
		// 随机产生0~3的数
		int c = rand() % 4;  // 0,1,2,3  对应运算符数组下标
		// 组包
		sprintf(buf, "%d%c%d=\n", a, ysf[c], b);
		printf(buf);
		// 写入到calc.txt文件中
		fputs(buf, fp);
	}
	// 关闭文件
	close_file(fp);
}

void read_data()
{
    
    	
	// 读取文件
	FILE* fp = open_file("r");
	int a, b = 0;
	char c = 0;
	char* p = NULL;
	char buf[128] = "";
	char new_buf[128] = "";
	int res = 0;
	while (1)
	{
    
    
		p = fgets(buf, sizeof(buf), fp); //读一行的数据72*65=\n
		if (NULL == p)
		{
    
    
			break;
		}
		// 拆包
		sscanf(buf, "%d%c%d", &a, &c, &b); // 72*65
		// switch判断运算符
		switch (c)
		{
    
    
		case '+':
			res = a + b;
			break;
		case '-':
			res = a - b;
			break;
		case '*':
			res = a * b;
			break;
		case '/':
			res = a / b;
			break;
		}
		// 再组包,将计算结果组进去
		sprintf(new_buf, "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\n
		printf("%s", new_buf);
	}
}

int main()
{
    
    	
	// 写入
	write_data();
	printf("\n");
	// 读取
	read_data();

	return 0;
}

Insert image description here

Step 3: If you write the result data directly from the second step, the original expression data will be overwritten, such ascalc.txtfile13+15=28\n34-21=13\n... Writing after reading the first \n will directly overwrite the data after \n, so the subsequent data cannot be read. The solution is Just save each row of packed data into a two-dimensional array

void read_data()
{
    
    	
	// 读取文件
	FILE* fp = open_file("r");
	int a, b = 0;
	char c = 0;
	char* p = NULL;
	char buf[128] = "";
	char new_buf[128] = "";
	int res = 0;
	// 定义二维数组保存每行组包结果数据
	char new_buff[10][128] = {
    
     0 };
	int i= 0;
	while (1)
	{
    
    
		p = fgets(buf, sizeof(buf), fp); //读一行的数据72*65=\n
		if (NULL == p)
		{
    
    
			break;
		}
		// 拆包
		sscanf(buf, "%d%c%d", &a, &c, &b); // 72*65
		// switch判断运算符
		switch (c)
		{
    
    
		case '+':
			res = a + b;
			break;
		case '-':
			res = a - b;
			break;
		case '*':
			res = a * b;
			break;
		case '/':
			res = a / b;
			break;
		}
		// 再组包,将计算结果组进去, 
		//sprintf(new_buf[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\n
		//printf("%s", new_buf);
		sprintf(new_buff[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\n
		i++;
		
	}
	// 关闭文件
	close_file(fp);
	// 再次打开calc.txt文件,写入含结果的四则运算表达式
	fp = open_file("w");
	for (int j = 0; j < i; j++)
	{
    
    
		fputs(new_buff[j], fp);
	}
	// 关闭文件
	close_file(fp);
}

Insert image description here

You can also write the newly packaged result data into a pointer array. You only need to apply for space with malloc to save the packaged data.

char* new_buff[10] = {
    
     NULL };
int i= 0;
while (1)
{
    
    
	p = fgets(buf, sizeof(buf), fp); //读一行的数据72*65=\n
	if (NULL == p)
	{
    
    
		break;
	}
	// 拆包
	sscanf(buf, "%d%c%d", &a, &c, &b); // 72*65
	// switch判断运算符
	switch (c)
	{
    
    
	case '+':
		res = a + b;
		break;
	case '-':
		res = a - b;
		break;
	case '*':
		res = a * b;
		break;
	case '/':
		res = a / b;
		break;
	}
	// 再组包,将计算结果组进去, 
	//sprintf(new_buf[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\n
	//printf("%s", new_buf);
	new_buff[i] = (char*)malloc(128);
	sprintf(new_buff[i], "%d%c%d=%d\n", a, c, b, res); // 72*65=4680\n
	i++;
}

3) Follow the format files fprintf and fscanf

3.1 Write files

  • Header file:#include <stdio.h>
  • Define function:int fprintf(FILE * stream, const char * format, ...);
  • Function: Convert and format data according to parameterformat string, and then output the result to the file specified by stream, specify the occurrence string end character'\0'.
  • Parameter:
    stream:Opened file
    format:String format, usage is the same asprintf()
  • Return value:
    Success: The number of characters actually written to the file
    Failure:-1

Example:UsefprintfProportionsprintOrganizationfputsCopying

printf("%04d:%02d:%02d", year, month, day);
sprintf(buf, "%04d:%02d:%02d", year, month, day)
fprintf(fp, "%04d:%02d:%02d", year, month, day)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>


int main()
{
    
    
	int year = 2022;
	int month = 12;
	int day = 2;
	char buf[128] = "";

	FILE* fp = NULL;
	fp = fopen("fprintf.txt", "w");
	if (!fp)
	{
    
    
		perror("open error");
		return -1;
	}
	// 组包
	sprintf(buf, "%04d:%02d:%02d", year, month, day);
	// 写入文件
	fputs(buf, fp);

	return 0;
}
	// 组包
	//sprintf(buf, "%04d:%02d:%02d", year, month, day);
	// 写入文件
	//fputs(buf, fp);
	//使用fprintf格式化写入文件
	fprintf(fp, "%04d:%02d:%02d", year, month, day);
	// 关闭文件
	fclose(fp);

Insert image description here

3.2 Reading files

  • Header file:#include <stdio.h>
  • Define function:int fscanf(FILE * stream, const char * format, ...);
  • Function: Read the string from the file specified by stream, and convert and format the data according to the parameter format string.
  • Parameter:
    stream:Opened file
    format:String format, usage is the same asscanf()
  • Return value:
    Success: number of parameters, number of successfully converted values
    Failure: - 1

Example:Usefscanfto unpack file data

scanf("%d:%d:%d", &year, &month, &day);
sscanf(buf, "%d:%d:%d", &year, &month, &day);
fscanf(fp, "%d:%d:%d", &year, &month, &day);
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>


int main()
{
    
    
	FILE* fp = NULL;
	fp = fopen("fprintf.txt", "r");  // 2022:12:02
	if (!fp)
	{
    
    
		perror("open error");
		return -1;
	}
	int year = 0, month = 0, day = 0;
	// 使用fscanf进行数据拆包
	fscanf(fp, "%d:%d:%d", &year, &month, &day);
	printf("%d-%d-%d", year, month, day);
	// 关闭文件
	fclose(fp);

	return 0;
}

Insert image description here

3.3 Intensive training: file version sorting

Write10 random numbers into abc.txt, and then sort the random numbers in the abc.txt file Write after

Insert image description here

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define CALC_NUM 10  // 要生成1~3位的整数个数
#define FILE_PATH "abc.txt"  // 文件路径


int main()
{
    
    
	// 设置随机种子,并写入数据
	FILE* fp = open_file("w");
	srand(time(NULL));
	for (int i = 0; i < CALC_NUM; i++)
	{
    
    
		// 产生随机数1~300
		int num = rand() % 300 + 1;
		// 格式化后写入
		fprintf(fp, "%d\n", num);
	}
	// 关闭文件
	close_file(fp);
	// 读取文件中写入的随机数,并保存到数组中
	int num = 0;
	int nums[10] = {
    
     0 };
	int n = sizeof(nums) / sizeof(nums[0]);
	fp = open_file("r");
	for (int i = 0; i < n; i++)
	{
    
    
		// 格式化读取字符串
		fscanf(fp, "%d", &num);
		// 将随机数保存到数组中
		nums[i] = num;
	}
	close_file(fp);
	// 对nums数组元素进行排序
	for (int i = 0; i < n - 1; i++) //比较的轮数
	{
    
    	// 因为每次比较的次数都要减1,刚好i每次加1,所以每一轮比较的次数就是n-1-i
		for (int j = 0; j < n - 1 - i; j++) // 每一轮比较的次数
		{
    
    
			if (nums[j] > nums[j + 1])  // 交换位置
			{
    
    
				int temp = nums[j];
				nums[j] = nums[j + 1];
				nums[j + 1] = temp;
			}
		}
	}
	// 再将排好序的nums数组写入到abc.txt文件
	fp = open_file("w");
	for (int i = 0; i < n; i++)
	{
    
    	
		// 将nums每个元素进行组包
		fprintf(fp, "%d\n", nums[i]);
	}
	close_file(fp);
	return 0;
}

Insert image description here

4) Read and write files fread and fwrite according to blocks

4.1 Write files

  • Header file:#include <stdio.h>
  • Define function:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • Function: Write content to the file in the form of data blocks
  • Parameter:
    ptr:The address to be written to file data
    size: size_t is of typeunsigned int. This parameter specifies the file to be written to. The block data size of the content
    nmemb:The number of blocks written to the file, the total size of the written file data is:size * nmemb
    stream:The open file pointer
  • Return value:
    Success: The number of blocks actually successfully written to the file data. This value is equal to Failed:nmemb
    0

Example:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>


typedef struct _std
{
    
    
	int age;
	char name[16];
}STD;

int main()
{
    
    	
	int cont = 0;
	STD buf[3] = {
    
     {
    
    20, "cdtaogang"}, {
    
    21, "laoli"}, {
    
    22, "laozhao"} };
	FILE* fp = fopen("fwrite.txt", "w");
	// fwrite 第二个参数写1 ,是为了返回值刚好是写入文件的字节数,这也是个技巧
	cont = fwrite(buf, 1, sizeof(buf), fp);
	// cont = fwrite(buf, sizeof(buf), 1, fp);
	// 验证返回值是否等于字节数
	if (cont == sizeof(buf))
	{
    
    
		printf("cont == sizeof(buf) == %d", cont); // 60 (int:4 + char name[16]:16)*3
	}

	return 0;
}

Insert image description here

4.2 Reading files

  • Header file:#include <stdio.h>
  • Define function:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • Function: Read content from the file in the form of data blocks
  • Parameter:
    ptr:The memory space to store the read data
    size: size_t is of typeunsigned int. This parameter specifies the read The block data size of the file content
    nmemb:The number of blocks to read the file, the total size of the read file data is:size * nmemb
    stream:The open file pointer
  • Return value:
    Success: The number of blocks that actually successfully read the content, if this value is smaller than nmemb, but larger than 0, indicating that the end of the file is read.
    failed:0

Example 1:Read the structure size one by one from the structure array

#pragma once
typedef struct _std
{
    
    
	int age;
	char name[16];
}STD;
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include "type.h"


int main()
{
    
    	
	// 定义结构体数组
	STD buf[3];
	// 全部设置为0
	memset(buf, 0, sizeof(buf));
	FILE* fp = NULL;
	fp = fopen("fwrite.txt", "r"); 
	if (!fp)
	{
    
    
		perror("open error");
		return -1;
	}
	int cont = 0;
	// 从结构体数组中,读取一个一个结构体大小
	for (int i = 0; i < 3; i++)
	{
    
    
		cont = fread(&buf[i], 1, sizeof(STD), fp);
		printf("cont=%d\n", cont);
		printf("%d %s\n", buf[i].age, buf[i].name);
	}

	return 0;
}
输出结果
cont=20
20 cdtaogang
cont=20
21 laoli
cont=20
22 laozhao

Example 2:Read the entire structure array size at once

int main()
{
    
    	
	// 定义结构体数组
	STD buf[3];
	// 全部设置为0
	memset(buf, 0, sizeof(buf));
	FILE* fp = NULL;
	fp = fopen("fwrite.txt", "r"); 
	if (!fp)
	{
    
    
		perror("open error");
		return -1;
	}
	int cont = 0;
	// 一次性读完整个结构体数组大小
	fread(buf, 1, sizeof(buf), fp);
	for (int i = 0; i < 3; i++)
	{
    
    
		printf("%d %s\n", buf[i].age, buf[i].name);
	}

	return 0;
}
输出结果
20 cdtaogang
21 laoli
22 laozhao

4.3 Intensive training: large file copy

Implement copying of large binary files

Insert image description here

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 1024 * 64



int main()
{
    
    
    printf("Start Copy\n");

    // 拷贝的源地址
    char* src_file = "a.mp4";
    // 拷贝的目标地址
    char* dst_file = "b.mp4";

    // 以 可读 + 二进制 方式打开文件
    // r 表示可读打开方式
    // 打开方式后添加 b , 表示以二进制形式打开
    FILE* p_src = fopen(src_file, "rb");
    // 如果打开失败 , 直接返回
    if (p_src == NULL) {
    
    
        printf("src_file open failed");
        return 0;
    }

    // 以 可写 + 二进制 方式打开文件
    // w 表示可写打开方式
    // 打开方式后添加 b , 表示以二进制形式打开
    FILE* p_dst = fopen(dst_file, "wb");
    // 如果打开失败 , 直接返回
    if (NULL == p_dst) {
    
    
        printf("dst_file open failed");
        return 0;
    }
    // 为缓冲区内存申请堆内存
    char* buffer = malloc(BUFFER_SIZE);

    // 判定文件指针是否指向文件末尾
    // 如果指向末尾 , 说明该文件
    while (!feof(p_src)) {
    
    
        // 读取源文件数据到 buffer 缓冲区, 读取 buffer_size 个字节
        // 如果没有那么多字节 , 将读取的字节数返回
        int res = fread(buffer, 1, BUFFER_SIZE, p_src);
        // 将读取到缓冲区中的数据写出到目标文件中
        fwrite(buffer, 1, res, p_dst);
    }

    // 释放缓冲区内存
    free(buffer);
    // 关闭源文件
    fclose(p_src);
    // 关闭目标文件
    fclose(p_dst);

    printf("Copy Success");

	return 0;
}

Insert image description here

Guess you like

Origin blog.csdn.net/qq_41782425/article/details/128071618