[C language] let you know how to perform file operations

Hello friends of csdn, in the process of learning C language, we can store different data by writing different codes. When the program is running, the data is stored in the memory, but when the program is closed, the data will naturally disappear. So what I want to share with you today is how to store data in files!

1. Why use files

When we studied the structure earlier, we wrote the program of the address book. When the address book is opened, there is data, and when the address book is closed, the data does not exist. This is because if we do not involvedocumentFor this thing, the data is instored in memoryyestemporary

So how can we save our data persistently?
This involves the problem of data persistence. Our general data persistence methods are:Store data in disk files, store in databasesand so on.

2. What is a file

Generally, everything that can be seen in our C drive and D drive can be calleddocument
But in programming, we generally talk about two kinds of files:program files, data files(Classified from the perspective of file function).

2.1 Program files

The .c file we write in C language, the object file (the suffix of the windows environment is .obj), and the executable program (the suffix of the windows environment is .exe) are all program files.

2.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 the file from which the program needs to read data, or the file that outputs the content.

Our address book is a program file, and what is used to store information in the address book is a data file
insert image description here

2.3 File name

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

3. File opening and closing

3.1 File Pointer

In the cache file system, the key concept is "file type pointer", referred to asfile pointer
Each used file has opened 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 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, namedFILE

insert image description here

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

3.2 Opening and closing of files

Files should be opened before reading and writing, and should be closed after use.
When writing a program, when opening a file, a FILE* pointer variable will be returned to point to the file, which is equivalent to establishing the relationship between the pointer and the file.
ANSIC stipulates that the fopen function is used to open the file, and the fclose is used to close the file.
insert image description here
insert image description here

//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );

The opening method is as follows
insert image description here
Let's try to write the code

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

Note: After the file fails to open, a null pointer will be returned, so we have to judgeFILE pointeris not a null pointer. When closing the file, we also put the pointernull pointer

4. Sequential reading and writing of files

After knowing how to open and close files, let me share with you the different ways of reading and writing files
insert image description here

4.1 fputc

The parameter of the fputc function is a pointer of FILE type, and the return value is an integer, which is used to output a character

insert image description here
Let's try to write 26 letters
Note: When there is no folder we want to input in the file, the computer will automatically create a new file in the .c file we wrote

int main()
{
    
    
	FILE* pf = fopen("test.txt", "w");//w为写文件
	if (pf == NULL)//判断是否为空指针
	{
    
    
		perror("fopen");
		return 1;
	}
	int i = 0;
	for (i = 0; i < 26; i++)
	{
    
    
		fputc('a'+i, pf);//fputc写文件
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here
Now open ourtxt file
insert image description here
So 26 letters aresuccessfully savedin the file

insert image description here

4.2 fgetc

The parameter of the fgetc function is also a pointer of FILE type, and the return value is an integer, which is used toread a character

insert image description here
upper code

int main()
{
    
    
	FILE* pf = fopen("test.txt", "r");//r为读文件
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	int ch;
	int i = 0;
	for (i = 0; i < 26; i++)
	{
    
    
		ch=fgetc(pf);//    fgetchar读文件
		printf("%c ", ch);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

Let's run it and find that the data we just entered into the folder is printed out by us again

insert image description here

4.3 fputs

fputs can write a string into our file, the function starts copying from the specified address (str) until it reaches the terminating null character ('\0') Note: The difference between
fput and put is not only that the target stream can be specified , and fput will not write other characters, while put will automatically append a newline at the end.

insert image description here

upper code

int main()
{
    
    
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}//我们想换行直接输入\n即可
	char arr[20] = "hello world\n";
	fputs(arr, pf);
	fputs("thank you\n", pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

In this way, we will enter the data into the test folder.

insert image description here

4.4 fgets

fgets can read from a streamread charactersand store it as a C string into str until (num-1) characters are read or until thenewline or end of file, whichever occurs first

insert image description here
upper code

int main()
{
    
    
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	char arr[20];
	fgets(arr, 5, pf);
	printf("%s", arr);
	fclose(pf);
	pf = NULL;
	return 0;
}

We needed to read 5 characters, but instead printed 4 characters. why?
This is because, fgets willAutomatically add a \0 to the last digit, so only num-1 characters are printed
insert image description here

4.5 fprintf

writes a C string pointing to the stream in format to the stream

insert image description here
upper code

struct s
{
    
    
	int a;
	float b;
	char arr[20];
};
int main()
{
    
    
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	struct s s = {
    
     10,3.14f,"hello world" };
	fprintf(pf,"%d %f %s", s.a, s.b, s.arr);
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here

4.6 fscanf

Read data from the stream and store it in the location pointed to by the additional parameter according to the parameter format

insert image description here
upper code

struct s
{
    
    
	int a;
	float b;
	char arr[20];
};
int main()
{
    
    
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	struct s s;
	fscanf(pf,"%d%f%s", &(s.a), &(s.b), s.arr);
	printf("%d %f %s", s.a, s.b, s.arr);
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here

4.55 The concept of streams

Have you noticed that the above functions are applicable to all input streams and all output streams, then流是什么呢

We can think of it as a stream of water, from which we can take water and put water. 数据就像一条水流一样. We may write data to files, screens, and networks (external devices) in the future, so we may need to know 外部设备knowledge, but these are too complicated for programmers, so the concept of streams is abstracted, and streams find how to write data to among external devices. For a programmer, he knows that reading data is read from the stream, and writing data is written to the stream. We don’t care about how the stream interacts with external devices. This is抽象出一个流的概念

When we read and write files, we operate one 文件流, including standard output stream stdout, standard input stream stdin, and standard error stream stderr. A C language program will open these three streams by default. The above-mentioned
insert image description here
insert image description here
functions applicable to all input and output streams are also suitable for standard I/O stream

int main()
{
    
    
	int ch = fgetc(stdin);
	printf("%c", ch);

	return 0;
}

4.6 Comparing a set of functions

scanf/fscanf/sscanf
printf/fprintf/sprintf

insert image description here

4.7 fwrite

fwrite can store a binary data into the stream

insert image description here

struct S
{
    
    
	char arr[10];
	int a;
	float b;
};
int main()
{
    
    
	struct S s = {
    
     "zhangsan",10,2.0f };
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	fwrite(&s, sizeof(s), 1, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here

At this time, the binary information is stored.

4.8 fread

fread can read binary information in the stream
insert image description here

struct S
{
    
    
	char arr[10];
	int a;
	float b;
};
int main()
{
    
    
	struct S s = {
    
     0 };
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	fread(&s, sizeof(s), 1, pf);
	printf("%s %d %f", s.arr, s.a, s.b);
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here

5. Random reading and writing of files

5.1 fseek

Locating the file pointer according to the position and offset of the file pointer can make our file pointer move arbitrarily

insert image description here
insert image description here

int main()
{
    
    
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	int ch = 0;
	ch = fgetc(pf);
	printf("%c ", ch);
	ch = fgetc(pf);
	printf("%c ", ch); 
	ch = fgetc(pf);
	printf("%c ", ch);
	ch = fgetc(pf);
	printf("%c ", ch);
	fseek(pf, -2, SEEK_CUR);
	ch = fgetc(pf);
	printf("%c ", ch);
	fseek(pf, 3, SEEK_SET);
	ch = fgetc(pf);
	printf("%c ", ch);
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here

5.2 ftell

Returns the offset of the file pointer relative to the starting position

insert image description here

int main()
{
    
    
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	long size;
	int ch = 0;
	ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c\n", ch);
	/*fseek(pf, -2, SEEK_CUR);
	rewind(pf);*/
	printf("%d", ftell(pf));
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here

5.3 find

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

insert image description here

int main()
{
    
    
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
		return 1;
	}
	long size;
	int ch = 0;
	ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c", ch);
	ch = fgetc(pf);
	printf("%c\n", ch);

	rewind(pf);
	size = ftell(pf);
	printf("%ld", size);
	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 file or binary file.
data inin memoryStored in binary form, if it is output to external storage without conversion, it is a binary file.
If it is required to store in the form of ASCII code on the external storage, it needs to be converted before storage. A file stored in the form of ASCII characters is a text file.
How is a piece of data stored in memory?
characterare always stored in ASCII form,numericData can be stored in either ASCII or binary form.
If there is an integer 10000, if it is output to the disk in the form of ASCII code, it will occupy 5 bytes (one byte for each character) on the disk, and if it is
output in binary form, it will only occupy 4 bytes on the disk (VS2013 test )

insert image description here
test code

int main()
{
    
    
	int a = 10000;
	FILE* pf = fopen("test.txt", "wb");
	fwrite(&a, 4, 1, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

insert image description here

7. Judgment of the end of file reading

Feof is judged after the end of file reading

insert image description here

insert image description here

7.1 misused feof

Keep in mind: during the file reading process, the return value of the feof function cannot be used to directly determine whether the file is over.
Instead, it is applied when the file reading ends, judging whether the reading fails to end, or the end of the file is encountered.

  1. Whether the reading of the text file is finished, 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, and judging whether the return 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.

Correct usage:
Example of text file:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    
    
    int c; // 注意:int,非char,要求处理EOF
    FILE* fp = fopen("test.txt", "r");
    if(!fp) {
    
    
        perror("File opening failed");
        return EXIT_FAILURE;
   }
 //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF
    while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环
   {
    
     
       putchar(c);
   }
   //判断是什么原因结束的
    if (ferror(fp))
        puts("I/O error when reading");
    else if (feof(fp))
        puts("End of file reached successfully");
    fclose(fp);
}

Example of a binary file:

#include <stdio.h>
enum {
    
     SIZE = 5 };
int main(void)
{
    
    
    double a[SIZE] = {
    
    1.,2.,3.,4.,5.};
    FILE *fp = fopen("test.bin", "wb"); // 必须用二进制模式
    fwrite(a, sizeof *a, SIZE, fp); // 写 double 的数组
    fclose(fp);
    double b[SIZE];
    fp = fopen("test.bin","rb");
    size_t ret_code = fread(b, sizeof *b, SIZE, fp); // 读 double 的数组
    if(ret_code == SIZE) {
    
    
        puts("Array read successfully, contents: ");
        for(int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
        putchar('\n');
   } else {
    
     // error handling
       if (feof(fp))
          printf("Error reading test.bin: unexpected end of file\n");
       else if (ferror(fp)) {
    
    
           perror("Error reading test.bin");
       }
   }
    fclose(fp);
}

8. File buffer

The ANSIC standard adopts the "buffer file system" to process data files. The so-called buffer file system refers to the systemautomaticallyCreate a block in memory for each file being used in the program"file buffer". The output data from the memory to the disk will be sent to the buffer in the memory first,After filling the buffersent to the disk together. If data is read from the disk to the computer, the data read from the disk file is input to the memory buffer (full of the buffer), 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
Here we test its buffer with code

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

A conclusion can be drawn here:
because of the existence of the buffer, when the C language operates files, it needs to doflush bufferor inend of file operationto close the file.
Failure to do so may cause problems reading and writing files

end

Like it first, watch it later, make it a habit! ! ^ _ ^
Code words are not easy, everyone's support is the motivation for me to persevere, don't forget to follow me after you like it!

If there are mistakes, please criticize and correct them (。ì_í。)

Guess you like

Origin blog.csdn.net/qq_65673848/article/details/129847875