[C language advanced] file operation

content

Why use files

what is a file

program files

data file

file name

file opening and closing

file pointer

file opening and closing

Sequential reading and writing of files

 fputc function

fgetc function 

fputc function 

fputs function 

 fgets function

fprintf function 

fscanf function 

fwrite function 

fread function 

sprintf and sscanf functions 

Random read and write of files

fseek function

ftell function

rewind function

Text files and binary files

Judgment of the end of file reading

misused feof

file buffer


Why use files

When we learned the structure earlier, we wrote the program of the address book. When the address book is running, we can add and delete data in the address book. At this time, the data is stored in the memory. When the program exits, the address book is stored in the address book. The data will naturally not exist. When the address book program is run next time, the data will have to be re-entered. It will be very uncomfortable to use such an address book.
We are thinking that since it is an address book, the information should be recorded. Only when we choose to delete the data, the data will no longer exist.
This involves the problem of data persistence. Our general data persistence methods include storing data in disk files, storing data in databases, and so on.
Using files, we can store data directly on the hard disk of the computer, which makes the data persistent.
 

what is a file

A file on disk is a file.
But in programming, we generally talk about two kinds of files: program files and data files (classified from the perspective of file functions).

program files

Including source program files (suffixed with .c), object files (with the suffix of .obj in the windows environment), and executable programs (with the suffix of .exe in the windows environment).

data file

The content of the file is not necessarily the program, but the data read and written when the program runs, such as the file from which the program needs to read data, or the file from which the content is output.

We are talking about data files here.

In the past, the input and output of the processed data were all based on the terminal, that is, the data was input from the keyboard of the terminal, and the running result was displayed on the display.

In fact, sometimes we will output the information to the disk, and then read the data from the disk into the memory for use when needed, and the file on the disk is processed here.

file name

A file must have a unique file identifier for user identification and reference.
The file name consists of 3 parts: file path + file name trunk + file suffix
For example:  d:\Ccode\test.txt
For convenience, the file identifier is often referred to as the file name.

file opening and closing

file pointer

In the buffer file system, the key concept is "file type pointer", referred to as "file pointer".
Each used file opens up a corresponding file information area in the memory, which is used to store the relevant information of the file (such as the name of the file, the state of the file and the current position of the file, etc.). This information is stored in a structure variable. The structure type is declared systematically and named FILE .

For example, the stdio.h header file provided by the VS2013 compilation environment has the following file type declaration:

struct _iobuf {
    char* _ptr;
    int   _cnt;
    char* _base;
    int   _flag;
    int   _file;
    int   _charbuf;
    int   _bufsiz;
    char* _tmpfname;
};
typedef struct _iobuf FILE;

The contents of the FILE types of different C compilers are not exactly the same, but they are similar.

Whenever a file is opened, the system will automatically create a variable of FILE structure according to the situation of the file, and fill in the information, the user does not need to care about the details. Generally, the variables of this FILE structure are maintained through a FILE pointer, which is more convenient to use.

Next we can create a pointer variable of FILE*:

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

Define pf to be a pointer variable to data of type FILE. You can make pf point to the file information area of ​​a file (it is a structure variable). The file can be accessed through the information in the file information area. That is, the file associated with it can be found through the file pointer variable.

for example:

file opening and closing

The file should be opened before reading and writing, and should be closed after the end of use.
When writing a program, when the file is opened, a pointer variable of FILE* will be returned to point to the file, which is also equivalent to establishing the relationship between the pointer and the file.
ANSIC specifies that the fopen function is used to open the file and fclose to close the file.

 

 

How the file is used

meaning  If the specified file does not exist
"r" (read only)

To enter data, open an existing text file

error
"w" (write only) To enter data, open a text file 3 create a new file
"a" (append) Append data to the end of a text file create a new file
"rb" (read only) To enter data, open a binary file error
"wb" (write only) To enter data, open a binary file create a new file
"ab" (append) Append data to the end of a binary file error
"r+" (read and write) Open a text file for reading and writing error
"w+" (read and write) Create a new text file for reading and writing create a new file
"a+" (read and write) Open a file for reading and writing at the end of the file create a new file
"rb+" (read and write) Open a binary file for reading and writing error
"wb+" (read and write) For reading and writing, create a new binary file create a new file
"ab+" (read and write) Open a binary file for reading and writing at the end of the file create a new file

int main()
{
    //打开文件
    FILE* pf = fopen("test.txt", "r");//当前路径
    FILE* pf = fopen("D:\\code\\test.txt", "r");//绝对路径 
    if (pf == NULL)
    {
        perror("fopen");
        return 0;
    }
    //读文件
    
    //关闭文件
    fclose(pf);
    pf = NULL;

    return 0;
}

Sequential reading and writing of files

 fputc function

#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件 - 输出操作
	//abcd - xyz
	char ch = 'a';
	for (ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, pf);
	}

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

fgetc function 


int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件 - 输入操作
	int ch = 0;
	while ((ch = fgetc(pf)) != EOF)//EOF是文件结束标记,值为-1
	{
		printf("%c ", ch);
	}
	
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

fputc function 

#include <stdio.h>

int main()
{
	//标准输入流 stdin 键盘
	//标准输出流 stdout 屏幕
	//标准错误流 stderr 屏幕
	int ch = fgetc(stdin);
	printf("%c\n", ch);
	fputc(ch, stdout);
	return 0;
}

fputs function 

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件 - 写一行
	fputs("qwerasdzxc", pf);
	fputs("xxxxxxxxxx\n", pf);
	fputs("abcdefghij", pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

 fgets function

int main()
{
	char arr[256] = { 0 };
	//打开文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	 }
	//读文件 - 写一行
	//fgets(arr, 25, pf);//最多读n-1个字符
	//printf("%s", arr);
	//fgets(arr, 25, pf);
	//printf("%s", arr);
    
	//fgets读取失败会返回NULL
	while (fgets(arr,256,pf)!=NULL)
	{
		printf("%s", arr);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

fprintf function 

struct S
{
	char name[20];
	int age;
	double score;
};

int main()
{
	
	struct S s = { "李四",20,87.2 };
	//打开文件

	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fprintf(pf, "%s %d %lf", s.name, s.age, s.score);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

fscanf function 

struct S
{
	char name[20];
	int age;
	double score;
};

int main()
{

	struct S s = { 0 };
	//打开文件

	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	fscanf(pf, "%s%d%lf", s.name, &(s.age), &(s.score));
	printf("%s %d %lf\n", s.name, s.age, s.score);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

fwrite function 

int main()
{
	struct S s = { "李四",20,87.2 };
	//写文件 - 二进制的方式写
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	//二进制的方式写文件

	fwrite(&s, sizeof(struct S), 1, pf);

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;

}

 

fread function 

int main()
{
	struct S s = { 0 };
	//写文件 - 二进制的方式写
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	//二进制的方式读文件

	fread(&s, sizeof(struct S), 1, pf);

	printf("%s %d %lf", s.name, s.age, s.score);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

 

Compare a set of functions

scanf/fscanf/sscanf
printf/fprintf/sprintf

scanf
formatted input function from the standard input stream (stdin)
fscanf formatted input function
for all input streams
sscanf
can extract (convert) formatted data from a string

printf
selects the formatted output function to the standard output stream (stdout)
fprintf the formatted output function
for all output streams
sprintf
converts a formatted data into a string

sprintf and sscanf functions 

struct S
{
	char name[20];
	int age;
	double score;
};

int main()
{
	char buf[256] = { 0 };
	struct S s = { "李四",20,87.2 };
	struct S ret = { 0 };

	//将s结构体数据转化为字符串
	sprintf(buf, "%s %d %lf", s.name, s.age, s.score);
	printf("%s\n", buf);//字符串的形式

	//从buf字符串从提取结构体数据
	sscanf(buf, "%s %d %lf", ret.name, &(ret.age), &(ret.score));
	printf("%s %d %lf", ret.name, ret.age, ret.score);//格式化的形式
	return 0;
}

 

Random read and write of files

fseek function

Locate the file pointer based on its position and offset

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//随机读

	int ch = fgetc(pf);
	printf("%c\n", ch);

	ch = fgetc(pf);
	printf("%c\n", ch);

	fseek(pf, -1, SEEK_END);

	ch = fgetc(pf);
	printf("%c\n", ch);

	fclose(pf);
	pf = NULL;
	return 0;
}

 

 

 

 

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//随机写
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	fputc('d', pf);

	fseek(pf, -3, SEEK_CUR);
	fputc('w', pf);

	fclose(pf);
	pf = NULL;
	return 0;
}

 

ftell function

 

Can calculate the offset of the current file pointer to the starting position

#include <stdio.h>

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//随机写
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	fputc('d', pf);

	fseek(pf, -3, SEEK_CUR);
	fputc('w', pf);
	long ret = ftell(pf);
	printf("%ld\n", ret);

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

rewind function

Return the position of the file pointer to the beginning of the file

 

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//随机写
	fputc('a', pf);
	fputc('b', pf);
	fputc('c', pf);
	fputc('d', pf);

	fseek(pf, -3, SEEK_CUR);
	fputc('w', pf);

	long ret = ftell(pf);
	printf("%ld\n", ret);

	rewind(pf);
	ret = ftell(pf);
	printf("%ld\n", ret);

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

 

Text files and binary files

Depending on how the data is organized, data files are called text files or binary files .
Data is stored in binary form in memory, and if it is output to external memory without conversion, it is a binary file .
If it is required to be stored in the form of ASCII code in external memory, it needs to be converted before storage. A file stored in ASCII characters is a text file .

How is data stored in memory?

Characters are always stored in ASCII form, and numeric data can be stored in either ASCII or binary form.
If there is an integer 10000, if it is output to disk in ASCII code , it will occupy 5 bytes on disk (one byte for each character), and if output in binary form , it will only occupy 4 bytes on disk ( 16 bytes). system storage ), is 10 27 00 00

 

Judgment of the end of file reading

misused feof

Remember: During the file reading process, the return value of the feof function cannot be used directly to determine whether the file is over.

Instead, it is used to judge whether the reading fails or the end of the file is encountered when the file reading ends .

1. Whether the reading of the text file is over, judge whether the return value is EOF ( fgetc ), or NULL ( fgets ).
For example:

fgetc judges whether it is EOF.
fgets judges whether the return value is NULL.

 
2. Judging the end of reading the binary file, judging whether the returned value is less than the actual number to be read.
For example:
fread judges whether the return value is less than the actual number to be read

int main()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	int ch = 0;
	//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
	while ((ch = fgetc(pf)) != EOF) // 标准C I/O读取文件循环
	{
		putchar(ch);
	}

	//判断是什么原因结束的
	if (ferror(pf))
		puts("I/O error when reading");
	else if (feof(pf))
		puts("End of file reached successfully");

	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

The ferror function judges whether it encounters an error and ends,

If no errors occurred in the stream, ferror will return 0. Otherwise, it will return a non-zero value.

The feof function judges whether it ends at the end of the file,

Returns 0 if the current position is not the end of the file. No errors are returned.

Be sure to judge after the file read fails! ! ! !

file buffer

The ANSIC standard uses the " buffer file system " to process data files. The so-called buffer file system means that the system automatically opens up a " file buffer " in memory for each file being used in the program . Data output from memory to disk will be sent to the buffer in memory first, and then sent to the disk after the buffer is full. If the data is read from the disk to the computer, the data is read from the disk file and input into the memory buffer (full buffer), and then the data is sent to the program data area (program variables, etc.) from the buffer one by one. The size of the buffer is determined by the C compilation system.
 

Under normal circumstances, when the buffer is full, the operating system will only allow the operating system to put the data in the buffer on the hard disk. 

#include <stdio.h>
#include <windows.h>

int main()
{
	FILE* pf = fopen("test.txt", "w");
	fputs("abcdef", pf);//先将代码放在输出缓冲区
	printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");
	Sleep(10000);//睡眠10秒
	printf("刷新缓冲区\n");
	fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
	//注:fflush 在高版本的VS上不能使用了
	printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");
	Sleep(10000);
	fclose(pf);
	//注:fclose在关闭文件的时候,也会刷新缓冲区
	pf = NULL;
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_54880517/article/details/124305391