(C language) Detailed explanation of file operations


1. Why use files

Before we learned about files, the data in the code were stored in memory. As long as the program exits, the data in the code will disappear. We need to re-enter the data the next time we run the code. This will be very troublesome
At this time, we can use files to store data directly on the computer disk to achieve data persistence

2. What is a file?

The files on the disk are files
In programming, we generally have two types of files: program files and data files

1. Program files

Program files include source program files (suffix .c), target files (suffix .obj in windows environment), and executable programs (suffix .exe in windows environment)

2.Data files

The content of the file is not necessarily the program, but the data read and written when the program is running, such as a file that needs to read data from when the program is running, or a file that outputs content.

3.File name

A file must have a unique file identifier to facilitate user identification and reference
The file name contains three parts: file path + file trunk + file suffix
For example: c:\code\test.txt
There are absolute paths and relative paths in the file path. This will be introduced later in opening and closing files

3. Opening and closing files

1. File pointer

When we perform a series of operations on files, we cannot do without the file pointer
File pointer:FILE*
FILE: Each used file has a corresponding file information area opened in the memory to store file-related information ( Such as the name of the file, the status of the file and the current location of the file, etc.). This information is stored in a structure variable. The structure type is declared by the system and named FILE
FILE*: Use a FILE pointer to maintain the variables of this FILE structure and operate the file

FILE* pf;//文件指针变量

pf is a pointer variable pointing to FILE type data, that is to say, The file associated with it can be found through the file pointer variable

2. Opening and closing files

The file should be opened before reading and writing, and the file should be closed after use.
In C language, it is stipulated that the fopen function should be used to open the file
https://legacy.cplusplus.com/reference/cstdio/fopen/?kw=fopen

FILE * fopen ( const char * filename, const char * mode );

The first parameter filename is the file name (including the file path), and the second parameter mode is the opening method. If the opening is successful, it returns the address of a structure pointer, otherwise it returnsNULL
Use the fclose function to close the file
https:// legacy.cplusplus.com/reference/cstdio/fclose/?kw=fclose
Returns 0 if closed successfully, otherwise returns a non-zero value
How to open the file As follows:
Insert image description here
Use of reading files

#include <stdio.h>
int main()
{
    
    
	//打开文件
	//FILE* pf = fopen(".\..\\..\\date.txt", "r");//相对路径  .表示当前路径..表示上一级路径
	//FILE* pf = fopen("G:\\summer_Classes\\2023\\text_10_15\\text_10_15\\date.txt", "r");//绝对路径
	FILE* pf = fopen("date.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	//写文件
	
	
	//关闭文件
	fclose(pf);
	pf = NULL;

	return 0;
}

Use of writing files

int main()
{
    
    
	//打开文件
	FILE* pf = fopen("date.txt", "w");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//写文件
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
    
    
		fputc(ch, pf);//fputc是一个字符输出函数
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here

4. Sequential reading and writing of files

Insert image description here
fputc character output function
https://legacy.cplusplus.com/reference/cstdio/fputc/?kw=fputc

int fputc ( int character, FILE * stream );
#include <stdio.h>
int main()
{
    
    
	char ch = 0;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
    
    
		if (ch % 5 == 0)
		fputc('\n', stdout);//stdout是标准输出流  stdin是标准输入流  stderr是标准错误流
		fputc(ch, stdout);
	}
	return 0;
}

fgetc character input function
https://legacy.cplusplus.com/reference/cstdio/fgetc/?kw=fgetc

int fgetc ( FILE * stream );
#include <stdio.h>
int main()
{
    
    
	FILE* pf = fopen("date.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//读文件
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF)
	{
    
    
		printf("%c ", ch);
	}

	fclose(pf);
	pf = NULL;
}

Insert image description here
fputs text line output function
https://legacy.cplusplus.com/reference/cstdio/fputs/?kw=fputs

int fputs ( const char * str, FILE * stream );
#include <stdio.h>
int main()
{
    
    
	FILE* pf = fopen("date.txt", "w");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//写文件
	fputs("hello", pf);
	char arr[] = "ward";
	fputs(arr, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here
fgets text line input function
https://legacy.cplusplus.com/reference/cstdio/fgets/?kw=fgets

char * fgets ( char * str, int num, FILE * stream );

The number of characters read by this function is num-1

#include <stdio.h>
int main()
{
    
    
	FILE* pf = fopen("date.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//读文件
	char arr[100] = {
    
     0 };
	fgets(arr, 3, pf);
	printf("%s ", arr);
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here
fprintf is the formatted output function
https://legacy.cplusplus.com/reference/cstdio/fprintf/?kw=fprintf

int fprintf ( FILE * stream, const char * format, ... );
#include <stdio.h>
struct S
{
    
    
	float f;
	char c;
	int n;
};

int main()
{
    
    
	struct S s = {
    
     3.14f,'z',20};
	FILE* pf = fopen("date.txt", "w");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//写文件
	fprintf(pf, "%f-%c-%d", s.f, s.c, s.n);
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here
fscanf formatted input function
https://legacy.cplusplus.com/reference/cstdio/fscanf/?kw=fscanf

int fscanf ( FILE * stream, const char * format, ... );
#include <stdio.h>
struct S
{
    
    
	float f;
	char c;
	int n;
};

int main()
{
    
    
	struct S s = {
    
     0 };
	FILE* pf = fopen("date.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//读文件
	fscanf(pf, "%f-%c-%d", &(s.f), &(s.c), &(s.n));
	printf("%f-%c-%d", s.f, s.c, s.n);
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here
fwrite binary output function
https://legacy.cplusplus.com/reference/cstdio/fwrite/?kw=fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

size_t size is the size of each element to be written
size_t count is the number of elements

#include <stdio.h>
int main()
{
    
    
	int arr[] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	//写文件
	FILE*pf = fopen("date.txt", "wb");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	//二进制的写文件
	fwrite(arr, sizeof(arr[0]), sizeof(arr)/sizeof(arr[0]), pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here
fread is a binary input function
https://legacy.cplusplus.com/reference/cstdio/fread/?kw=fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

size_t size is the size of each element to be read
size_t count is the number of elements

#include <stdio.h>
int main()
{
    
    
	int arr[10] = {
    
    0};
	//写文件
	FILE* pf = fopen("date.txt", "rb");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	//二进制的读文件
	fread(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pf);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here
What is read here is the binary file we wrote before using fwrite.

Although the following two functions have little to do with file operations, they are easily confused with file operation functions
sprintf converts formatted data into strings
https://legacy.cplusplus.com/reference/cstdio/sprintf/?kw=sprintf

int sprintf ( char * str, const char * format, ... );
#include <stdio.h>
struct S
{
    
    
	float f;
	char c;
	int n;
};

int main()
{
    
    
	struct S s = {
    
     3.14f,'z',20 };
	char arr[100] = {
    
     0 };
	sprintf(arr, "%f-%c-%d", s.f, s.c, s.n);
	printf("%s\n", arr);
	return 0;
}

Insert image description here
sscanf converts strings into formatted data
https://legacy.cplusplus.com/reference/cstdio/sscanf/?kw=sscanf

int sscanf ( const char * s, const char * format, ...);
#include <stdio.h>
struct S
{
    
    
	float f;
	char c;
	int n;
};

int main()
{
    
    
	struct S s = {
    
     3.14f,'z',20 };
	char arr[100] = {
    
     0 };
	sprintf(arr, "%f-%c-%d", s.f, s.c, s.n);
	printf("%s\n", arr);

    struct S tmp = {
    
     0 };
    sscanf(arr, "%f-%c-%d", &(tmp.f), &(tmp.c), &(tmp.n));
    printf("%f\n", tmp.f);
    printf("%c\n", tmp.c);
    printf("%d\n", tmp.n);
	return 0;
}

Insert image description here

5. Random reading and writing of files

1.fseek

Define the file pointer based on its position and offset
https://legacy.cplusplus.com/reference/cstdio/fseek/?kw=fseek

int fseek ( FILE * stream, long int offset, int origin );

Insert image description here
stream: file stream
offset: offset
origin: is the starting position, there are three positioning pointers
Return value:
1. If successful, fseek returns 0;
2. Otherwise, it returns a non-zero value;
3. On devices that cannot be found, the return value is undefined;

#include <stdio.h>
int main()
{
    
    
	FILE* pf = fopen("date.txt", "r");
	if (pf == NULL) {
    
    
		perror("fopen");
		return 1;
	}
	//读文件
	int ch = fgetc(pf);
	printf("%c\n", ch);//a
	ch = fgetc(pf);
	printf("%c\n", ch);//b
	ch = fgetc(pf);
	printf("%c\n", ch);//c
	ch = fgetc(pf);
	printf("%c\n", ch);//d
	要拿到当前文件指针所处位置向前偏移4个单位的字符
	fseek(pf, -4,SEEK_CUR);
	ch = fgetc(pf);
	printf("%c\n", ch);//a
	//要读取从头开始向后偏移1个单位的一个字符
	fseek(pf, 1, SEEK_SET);
	ch = fgetc(pf);
	printf("%c\n", ch);//b
	//要拿到文件流末尾向前偏移9个单位的一个字符
	fseek(pf, -9, SEEK_END);
	ch = fgetc(pf);
	printf("%c\n", ch);//a
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here

2.ftell

Returns the offset of the file pointer from the starting position
https://legacy.cplusplus.com/reference/cstdio/ftell/?kw=ftell

long int ftell ( FILE * stream );
#include <stdio.h>
int main()
{
    
    
	FILE* pf = fopen("date.txt", "r");
	if (pf == NULL) {
    
    
		perror("fopen");
		return 1;
	}
	//读文件
	int ch = fgetc(pf);
	printf("%c\n", ch);//a
	ch = fgetc(pf);
	printf("%c\n", ch);//b
	ch = fgetc(pf);
	printf("%c\n", ch);//c
	ch = fgetc(pf);
	printf("%c\n", ch);//d
	int pos = ftell(pf);
	printf("pos = %d\n", pos);
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here

3.rewind

Return the position of the file pointer to the starting position of the file
https://legacy.cplusplus.com/reference/cstdio/rewind/?kw=rewind

void rewind ( FILE * stream );
#include <stdio.h>
int main()
{
    
    
	FILE* pf = fopen("date.txt", "r");
	if (pf == NULL) {
    
    
		perror("fopen");
		return 1;
	}
	//读文件
	int ch = fgetc(pf);
	printf("%c\n", ch);//a
	ch = fgetc(pf);
	printf("%c\n", ch);//b
	ch = fgetc(pf);
	printf("%c\n", ch);//c
	ch = fgetc(pf);
	printf("%c\n", ch);//d
	rewind(pf);
	ch = fgetc(pf);
	printf("%c\n", ch);//a
	fclose(pf);
	pf = NULL;
	return 0;
}

Insert image description here

6. Text files and binary files

Depending on how the data is organized, data files are calledtext filesorbinary files a>text files if required. If it is stored in ASCII code in external memory, it needs to be converted before storage. Files stored in the form of ASCII characters arebinary file
The data is stored in binary form in the memory. If it is output to external memory without conversion, it is a

7. Determination of the end of file reading

Incorrectly used feof
Remember: During the file reading process, the return value of the feof function cannot be used to directly determine whether the file is ended.
Instead, it is used when the file reading ends to determine whether the reading fails or the end of the file is encountered.
Text file:
If fgetc() is used to read, it is necessary to determine whether the return value of feof() is EOF;
If fgets() is used to read, it is necessary to determine whether the return value of feof() is NULL;
binary Files:
are all read using fread(). It is necessary to judge the size of the return value and the specified number of reads. If it is smaller than the actual number to be read, it means that a read exception has occurred. If it is equal to the actual number to be read, it means that the reading ended successfully;
For the judgment of reading exception, we consider judging the return value of the ferror() function:
1. If error() is true - abnormal reading ends;
1. If feof() is true - normal reading ends; a>

8. File buffer

ANSIC standard adopts "buffer file system" to process data files. The so-called buffer file system means that the system automatically allocates a block in memory for each file being used in the program.File buffer". The data output from the memory to the disk will be sent to the buffer in the memory first, and then sent to the disk together after the buffer is filled. If data is read from the disk to the computer, the data is read from the disk file and input into the memory buffer (the buffer is filled), and then the data is sent from the buffer to the program data area (program variables, etc.) one by one. The size of the buffer is determined by the C compilation system
Insert image description here


Guess you like

Origin blog.csdn.net/2301_78373304/article/details/133841922