c language--file operation (1)

Table of contents

1. Why use files

2. What is a file

 2.1 Program files

2.2 Data files

2.3 File name

3. Opening and closing files

3.1 File pointer

3.2 Opening and closing files

4. Sequential reading and writing of files

fputs function example:

fgetc function example 

4.1 The concept of flow

4.2 Compare several groups of functions:

fprintf function:

fscanf function:

fwrite and fread functions:

5. Random reading and writing of files

5.1 fseek function

5.2 ftell

5.3 rewind


1. Why use files

        When we study structures, we may have written address book programs. When the address book is running, we can add and delete data to the address book. At this time, the data is stored in the memory. When the program exits , the data in the address book will naturally no longer exist. The next time you run the communication recording program, the data will have to be re-entered. It will be very uncomfortable if you 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 issue of data persistence. Our general data persistence methods include storing data in disk files, storing data in databases, etc. Using files, we can store data directly on the computer's hard drive, achievingdata persistence.


2. What is a file

The files on disk are files.
        But in programming, we generally talk about two types of files: program files and data files (from File function classified from the angle).

 2.1 Program files

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

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 a file that needs to read data from when the program is running, or a file that outputs content.


 This chapter discusses data files.
        In the previous chapters, the input and output of data processed were all targeted at the terminal, that is, data is input from the keyboard of the terminal, and the running results are displayed on the monitor. In fact, sometimes we output the information to the disk, and then read the data from the disk into the memory for use when needed. What is processed here is the file on the disk.

2.3 File name

A file must have a unique file identifier to facilitate user identification and reference.
The file name contains 3 parts: file path + file name trunk + file suffix
For example: c:\code\test.txt
For convenience, the file identifier is often called the file name.


3. Opening and closing files


3.1 File pointer

        In the buffered file system, the key concept is the "file type pointer", referred to as the "file pointer".
        Each used file opens up a corresponding file information area in the memory, which is used to store file-related information (such as file name, file status and 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.

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 type 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 the FILE structure based on the file's condition, and Fill in the information without the user having to worry about the details.


        Generally, the variables of this FILE structure are maintained through a FILE pointer, which makes it more convenient to use.
Below we can create a pointer variable of FILE*:

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

        Define pf as a pointer variable pointing to FILE type data. You can make pf point to the file information area of ​​a certain file (it is a structure variable). The file can be accessed through the information in the file information area. In other words, the file associated with it can be found through the file pointer variable.
For example:


3.2 Opening and closing files

        The file should be opened before reading or writing, and the file should be closed after use.
        When writing a program, when opening a file, a FILE* pointer variable pointing to the file will be returned. , which is also equivalent to establishing the relationship between pointers and files.
        ANSIC requires the use of fopen function to open the file, fclose to close the file.

//打开文件
FILE * fopen ( const char * filename, const char * mode );//参数 文件名,打开方式
//关闭文件
int fclose ( FILE * stream );//参数 文件指针

How to open the file:

How to use files meaning If the specified file does not exist
"r" (read only) To enter data, open an existing text file Error
"w" (write only) To output the data, open a text file Create a new file
“a” (add) Add data to the end of text file Create a new file
"rb" (read-only) To enter data, open a binary file Error
"wb" (write only) To output data, open a binary file Create a new file
“ab” (add) Add data to the end of a binary file Error
"r+" (read and write) For reading and writing, open a text file Error
"w+" (read and write) For reading and writing, a new file is recommended Create a new file
"a+" (read and write) Open a file and read and write 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 and read and write at the end of the file Create a new file

for example:

#include<stdio.h>
int main()
{
	//以写的形式打开文件
	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	//关闭文件
	fclose(pf);
	pf = NULL;//置空,防止野指针
}

 

We can check in the current path that the file has indeed been generated.


What happens if the file is opened in read-only mode but the file is not created?

#include<stdio.h>
int main()
{
	//以读的形式打开文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	//关闭文件
	fclose(pf);
	pf = NULL;//置空,防止野指针
}

        To open a file in read-only mode, you must first create the file in the current path before you can open it. Unlike writing-only, you cannot create a new file yourself.


4. Sequential reading and writing of files

Function Function name Applicable to
Character input function fgetc all input streams
character output function fputc All output streams
Text line input function fgets all input streams
Text line output function fputs All output streams
Format input function fscanf all input streams
Format output function fprintf All output streams
binary input fread document
binary output fwrite document

The red markers are for text files, while binary input and output are for binary files.

fputs function example:

include<stdio.h>
int main()
{
	//以写的形式打开文件
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
	}
	//写文件
	char ch = 0;
	for (ch = 'a'; ch < 'z'; ch++)
	{
		fputc(ch, pf);
	}
	//关闭文件
	fclose(pf);
	
	pf = NULL;//置空,防止野指针
}

 Program running effect

        At this time we see that 26 letters have been entered into the test.txt file. When we use the fputc function, every time we enter a letter into the file, the pointer to the file status (can be understood as the cursor) will move backward by one Bit. (Not the movement of the file pointer (pf))


fgetc function example 

#include<stdio.h>
int main()
{
	//以读的形式打开文件
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	//读文件
	char ch = 0;
	while ((ch = fgetc(pf))!= EOF)
	{
		printf("%c", ch);
	}
	//关闭文件
	fclose(pf);
	
	pf = NULL;//置空,防止野指针
}

operation result:


4.1 The concept of flow

When we used the function for the file, we saw all the output streams and all the input streams. So what are the streams?

        ​ ​ ​ First of all, flow is a highly abstract concept. Computers are composed of many external devices. When we operate external devices, the operating methods of each device are different, which places higher requirements on technical personnel. In order to simplify this operation, just between data and external devices The stream is abstracted in time, and the programmer only needs to write data into the stream. The C language will operate these streams and flow them to the computer's external devices.

In fact, when we write a file, we open the file and close the file.

scanf reads data from the keyboard

printf prints data to the screen

Just do it directly.

That's because: as long as the C language program is run, 3 streams are opened by default.

1.Standard input stream----stdin

2. Standard output stream----stdout

3. Standard error stream----stderr

The pointers maintaining these three streams are all FILE*

Since fputc applies to all output streams, we can print directly to the screen:

#including<stdio.h>
int main()
{
    for (ch = 'a'; ch < 'z'; ch++)
	{
		fputc(ch, stdout);
	}
    return 0;
}


4.2 Compare several groups of functions:

scanf/fscanf
printf/fprintf

fprintf function:

        You can see that fprintf has one more parameter than printf - file stream.

 

  Function usage:

#include<stdio.h>
struct S
{
	float f;
	char c;
	int n;
};

int main()
{
	struct S s = { 3.14f, 'w', 100 };

	FILE* pf = fopen("data.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fprintf(pf, "%f-%c-%d", s.f, s.c, s.n);

	fclose(pf);
	pf = NULL;

	return 0;
}

The data is written directly to the file.


fscanf function:

        The same fscanf has one more parameter than scanf - file stream

Function usage: 

struct S
{
	float f;
	char c;
	int n;
};

int main()
{
	struct S s = {0};

	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读文件
	fscanf(pf, "%f-%c-%d", &(s.f), &(s.c), &(s.n));
	printf("%f-%c-%d\n", s.f, s.c, s.n);

	fclose(pf);
	pf = NULL;

	return 0;
}

Successfully read the data.​ 


fwrite and fread functions:

fwrite can write data to a file in binary form

Parameter explanation: 

        ptr: Pointer to the data block to be written.​ 

        size: The size of each data item (in bytes).​ 

        Count: The number of data items to be written.​ 

        ​​​​stream: The file pointer to which data is to be written.

fread can read data from a file in binary form

Function usage: 

#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//写文件
	FILE*pf = fopen("data.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;
}

        We see that the file displays garbled characters. This is because the file cannot recognize binary data, but the data is indeed stored in the file. We can use the fread function to verify it.

//二进制的方式读取文件
int main()
{
	int arr[10] = {0};
	//写文件
	FILE* pf = fopen("data.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;
}

We can see that the information in the file was successfully read.


5. Random reading and writing of files


5.1 fseek function

Position the file pointer based on its position and offset.

Parameter explanation:

        ​ ​ ​ Stream: The file pointer to be located.

        Offset: Offset, that is, the number of bytes to be moved.

        Origin: starting position, specifying the position from which the offset is calculated. Can be one of the following values:

        SEEK_SET: Calculate the offset from the beginning of the file.

        SEEK_CUR: Calculate the offset from the current file pointer position.

        SEEK_END: ​​Calculate the offset from the end of the file.

 

 for example:

        We filled in abcdef in the file and performed four output operations. The offset position came to d, but we also want to output c. How to use the fseek function to achieve this effect.

#include<stdio.h>
int main()
{
	FILE* pf = fopen("data.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
	fseek(pf, -2, SEEK_CUR);//从文件当前位置向左移动两个偏移量
	ch = fgetc(pf);
	printf("%c\n", ch);//b

	return 0;
}

Just move the offset two places to the left.​ 

5.2 ftell

Returns the offset of the file pointer relative to the starting position. As long as there is a file stream pointer when passing parameters.

 

for example:

int main()
{
	FILE* pf = fopen("data.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);

	return 0;
}

operation result:


5.3 rewind

Return the file pointer to the beginning of the file.

 

Guess you like

Origin blog.csdn.net/2301_76618602/article/details/133672673