C language file operation details

Posted by daveeboi on Sun, 21 Nov 2021 08:55:45 +0100

catalogue

Concept of document

  Classification of documents

  Classification of data files

text file

  Binary file

  File operation

  Opening and closing of files

  Open file

  Close file

  field name pointer

file name  

file buffer

Second argument to fopen function

  Sequential reading and writing of files

 Sequential read-write function of file  

  fputc and fgetc functions

 fputs and fgets functions

  fscanf and fprintf functions

  sscanf and ssprintf

  fwrite and fread

Random reading and writing of files  

fseek function  

ftell function

remind function  

Find the size of a file

File decision function

  ferror function

  feof function

Concept of document

  Classification of documents

A file is a collection of related data. In C programming, it can be divided into two categories according to the contents of documents:

One is the program file, which is the source code of the program. For example, test..c in the figure is the program file. Of course, the object file (. obj) and program file (. exe) generated by the compiler under windows are all program files

The other is the data file, which is the original data and output results required by the program running, such as data.txt in the figure

Both types of files are saved on disk and can be used at any time.

Naturally, there is no need to explain the operation of program files. Here is about the operation of data files, that is, how to manage data files through relevant functions in program files

  Classification of data files

  According to the storage form of data, data files can be divided into text files and binary files.

text file

  The data.txt in the figure above is a text file

A text file, also known as an ASCII file, is a character stream file. The file is formed by connecting the beginning and end of each character, in which each character occupies 1 byte and stores the · ASCII code of the character  .

For example, an int integer - 25612 is stored in binary form in memory, accounting for 4 bytes, while in a text file, it is stored in written form - 25612, accounting for one byte per character, accounting for 6 bytes in total.

In the program file, to write the number into the text file, first convert the 4-byte binary number in the memory into 6-character ASCII code; If you want to read the number from the text file into the memory, that is, if the program file wants to read the data from the text file, you must first convert the six characters into a 4-byte binary number. Of course, the operating system will help us complete the conversion process.

  Binary file

Data in binary file   It is stored according to its storage form in memory.

For example, a double constant of 1.0, regardless of its writing form, accounts for 8 bytes in memory and binary files.

Since binary files do not need to be converted during input / output, they are highly efficient, but binary files can only be read by machines and cannot be read manually; Moreover, different computer systems have different binary representations of data, so the portability is poor. Binary files are generally used to save the intermediate results of data processing.

 

Generate the binary file test.txt through the program file above and write data "Zhang San", 20, 99.2f

 

  Visible binary files cannot be read directly by human

  File operation

  Opening and closing of files

We need to open the file before reading and writing, and close the file after use.  

  Open file

The standard library function fopen is used to inform the compiler system of three information: the file name to be opened; How files are used (read-only, write only, or both); Returns a file pointer to the compiler.

Function prototype: FILE *fopen(const char *path, const char *mode);

Return value: NULL will be returned if opening the file fails, and a file pointer will be returned if it succeeds

  Close file

Use the standard library function fclose. Its function is to write the data to the disk (the data may still be in the buffer), cut off the connection between the file pointer and the file, and release the structure variable. If you don't close it, you will probably lose data, and the number of files opened at the same time is limited. (when the program runs normally, the system will automatically close all open files)

Function prototype: int fclose(FILE *fp);

Note that the fclose function will not set the fp pointer to NULL. Therefore, to prevent misuse, we need to manually set fp=NULL;

I believe the little partner will have three questions: what is the file pointer? Why should the first parameter of fopen be path instead of file name? What is the buffer? The guests looked down carefully.

  field name pointer

  The operating system declares a structure

For example, the stdio.h header file provided by the VS2008 compilation environment contains the following file type declarations:
struct _iobuf {
    char *_ptr;
    int    _cnt;
    char *_base;
    int    _flag;
    int    _file;
    int    _charbuf;
    int    _bufsiz;
    char *_tmpfname;
};
typedef struct _iobuf FILE;  

  When we use the fopen function to open a FILE, the operating system helps us create a structure variable of FILE type. How to return the address of the structure variable through fopen, so we need to define a pointer of FILE type to receive the address of the structure variable.

This structure variable is used to store the relevant information of the file (such as file name, file status, current location, etc.)

A pointer of type FILE is a FILE pointer  , Manage the FILE through the FILE pointer

file name  

  A file should have a unique file ID so that users can identify and reference it.
File identification consists of three parts: file path + file name trunk + file suffix
For convenience, the file ID is often referred to as the file name.

 

  Now you know why the first parameter of fopen is path

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" for each file being used in the program in memory.

The data output from memory to disk will be sent to the output buffer in memory first, and then sent to the disk together after the output buffer is filled (if the extraction closes the file or the program ends, the data can be sent to the disk even if the buffer is not full).
When data is read from the disk to the computer, the data is read from the disk file and input into the input buffer of the memory. The data is sent to the program data area (program variables, etc.) one by one from the input buffer through the function. The size of the buffer is determined according to the C compilation system
 

Second argument to fopen function

The second parameter is how to use the file. There are the following types

File usage

meaning

Specifies the status of the file

"r" (read only)

To enter data, open an existing text file

File does not exist or read error is not allowed (i.e. NULL is returned)

"w" (write only)

In order to output data, open a text file (empty the original content)

If the file does not exist, a new file is created. If it exists, the original content is cleared and written from the starting position

"a" (added)

Add data to the end of a text file

File does not exist. Create a new file. If it exists, write data after the original content

"rb" (read only)

To enter data, open a binary file

File does not exist or read error is not allowed (i.e. NULL is returned)

"wb" (write only)

To output data, open a binary file

If the file does not exist, a new file is created. If it exists, the original content is cleared and written from the specified location

"ab" (additional)

Add data to the end of a binary file

File does not exist. Create a new file. If it exists, write data after the original content

"r +" (read / write)

To read and write, open a text file

There is no error in the file (NULL is returned). If the file exists, the reading and writing always start from the starting position of the file (the starting position of the file can be set by the location function). When writing new data, only the space occupied by the data is overwritten, and the subsequent old data is not lost

"w +" (read / write)

To read and write, open a text file (empty the original content)

If it does not exist, a new file is created (the starting position of the file can be set by the location function)

"a +" (read / write)

Open a file and read and write at the end of the file

If the file does not exist, create a new file. If it exists, write data after the original content. After adding new data at the end of the file, you can read it from the beginning (to move the file position pointer). The starting position of the file can be set by the position function,

"rb +" (read / write)

Open a binary file for reading and writing

If there is no error in the file (NULL is returned), the starting position of the file can be set by the location function when reading and writing. When writing new data, only the space occupied by the data is overwritten, and the subsequent old data is not lost

"wb +" (read / write)

To read and write, open a binary file (empty the original content)

If it does not exist, a new file is created. The starting position of the file can be set by the location function when reading and writing

"ab +" (read / write)

Open a binary file and read and write at the end of the file

If the file does not exist, create a new file. If it exists, write data after the original content. After adding new data at the end of the file, the starting position of the read file can be set by the position function

  Sequential reading and writing of files

Sequential read-write function of file  

function

Function name

Apply 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

Format input function

sscanf

character string

Format output function

sprintf

character string

Binary input

fread

file

Binary output

fwrite

file

  fputc and fgetc functions

  Function prototype: int fputc(int c, FILE *stream);

The function is to output a character to a specified position

Return value: the characters passed in by the user will be returned if the output is successful, and EOF will be returned if the output fails (it is a macro and the end of file flag, with a value of - 1)

  The first parameter of fputc function is the character to be output, and the second parameter is the output position of the character, that is, the file pointer defined by us,.

#include<stdio.h>

int main() {
	FILE* fp = fopen("test.txt", "w");
	if (fp == NULL) {
		perror("open file for writting");
		return 1;
	}
	char arr[] = { "hello world!!!" };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//Write file
	for (int i = 0; i < sz; i++) {
		if (fputc(arr[i], fp) < 0) {
			perror("write failed");
			return 2;
		}
	}

	//Close file
	fclose(fp);
	fp = NULL;
	return 0;
}

Function prototype: int fgetc(FILE *stream);

Function: read a character from the specified position

Return value: this character is returned after reading successfully. EOF is returned if the file is read or an error occurs

#include<stdio.h>

int main() {
	FILE* fp = fopen("test.txt", "r");
	if (fp == NULL) {
		perror("open file for writting");
		return 1;
	}
	char arr[20] = { 0 };
	//Write file
	for (int i = 0; i < 20; i++) {
		if ((arr[i]=fgetc(fp))<0) {
			printf("read end\n");
			break;
		}
	}

	for (int i = 0; i < 20; i++) {
		printf("%c", arr[i]);
	}
	printf("\n");
	//Close file
	fclose(fp);
	fp = NULL;
	return 0;
}

fputs and fgets functions

  Function prototype: int fputs(const char *s, FILE *stream);

Parameter: the first parameter is the string to be output, and the second parameter is the output position of the string  

Function: output a string to the specified location

Return value: a non negative number is returned for success, and EOF is returned for failure

#include<stdio.h>

int main() {
	FILE* fp = fopen("test.txt", "w");
	if (fp == NULL) {
		perror("open file for writting");
		return 1;
	}
	if (fputs("hello world!!!", fp) < 0) {
		perror("write failed");
		return 2;
	}

	//Close file
	fclose(fp);
	fp = NULL;
	return 0;
}

Function prototype: char *fgets(char *s, int size, FILE *stream);

Parameters: the first parameter is the storage location of the data you read

            The second parameter is the number of characters you want to read

            The third parameter is the file pointer of the file you want to read,

Function: read the data of the specified number of characters from the specified position and store it in the specified position.

Return value: if successful, the address of the location where the data is stored is returned. If an error occurs or the end of the file is read, a null pointer (NULL) is returned.

#include<stdio.h>

int main() {
	FILE* fp = fopen("test.txt", "r");
	if (fp == NULL) {
		perror("open file for writting");
		return 1;
	}
	char arr[20] = { 0 };
	//Write file
	if (fgets(arr, 20, fp) == NULL) {
		perror("read failed");
		return 2;
	}

	for (int i = 0; i < 20; i++) {
		printf("%c", arr[i]);
	}
	printf("\n");
	//Close file
	fclose(fp);
	fp = NULL;
	return 0;
}
If the fgets function does not encounter a newline character ('\ n') when reading the N - 1 character, it returns the read n - 1 character and adds a '\ 0' at the end( Actually read valid characters (n-1) If a newline character ('\ n') is read before the nth character is read by the fgets function, the reading will be stopped, and the character brought back by the reading will contain the newline character.

  fscanf and fprintf functions

Function prototype: int fprintf(FILE *stream, const char *format,...);

Compare int printf(const char *format,...); It is found that fprintf has one more parameter of FILE * type than printf

printf outputs content to the display, while fprintf outputs content to stream  , There is no other difference between the two

#include<stdio.h>

int main() {
	FILE* fp = fopen("test.txt", "w");
	if (fp == NULL) {
		perror("open file for writting");
		return 1;
	}
	fprintf(fp, "%s\n", "HELLO WORLD");
	fprintf(fp, "%s\n", "HELLO EVERYONE");

	//Close file
	fclose(fp);
	fp = NULL;
	return 0;
}

 

Function prototype: int fscanf(FILE *stream, const char *format,...);

Compare int scanf(const char *format,...); It is found that fscanf has one more parameter of FILE * type than scanf  

scanf obtains data from the keyboard and fscanf obtains data from the stream. There is no other difference between the two

#include<stdio.h>

int main() {
	FILE* fp = fopen("test.txt", "r");
	if (fp == NULL) {
		perror("open file for writting");
		return 1;
	}
	char arr[30] = { 0 };
	fscanf(fp, "%s", arr);

	for (int i = 0; i < 30; i++) {
		printf("%c", arr[i]);
	}
	printf("\n");
	//Close file
	fclose(fp);
	fp = NULL;
	return 0;
}

  sscanf and ssprintf

The header files for both are < string. H >  

  Function prototype: int sscanf(const char *str, const char *format,...);

        Function: get data from str string for output

  Function prototype  : int sprintf(char *str, const char *format, ...);

        Function: output data to str

#include<stdio.h>
#include<string.h>

int main() {

	char arr[20] = { 0 };
	char arr1[20] = { 0 };
	sprintf(arr, "%s", "hello world!!!");
	sscanf(arr, "%s", arr1);
	printf("%s\n", arr);
	printf("%s\n", arr1);
	return 0;
}

  fwrite and fread

Function prototype: size_t fwrite(const void *ptr,                                                                                                                             size_t size,                                                                                                                                 size_t nmemb,
                                    FILE *stream);

Parameters: the first parameter ptr is the pointer to a data block (the data block is used to provide data), the second parameter is the number of bytes of the data block, the third parameter is the number of data blocks, and the fourth parameter is the target location of data output

Function: store data to files in binary form

Return value: returns the number of complete items actually written. If an error occurs, the number may be less than nmemb

#include<stdio.h>

struct Stu
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct Stu s = { "Zhang San", 20, 99.2f };
	FILE* pf = fopen("test.txt", "wb");
	if (pf == NULL)
	{
		perror("open file for writting");
		return 1;
	}
	//Write file
	fwrite(&s, sizeof(struct Stu), 1, pf);
	//Close file
	fclose(pf);
	pf = NULL;
	return 0;
}

  Function template: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

Parameter: the first parameter ptr points to a data block (the data block is used to receive data), the second parameter is the number of bytes of the data block, the third parameter is the number of data blocks, and the fourth parameter is used to provide data

Function: read data from binary text

Return value: the total number of elements successfully read. If this number is different from the nmemb parameter, it may be that a read error occurred during reading or the end of the file was reached

#include<stdio.h>

struct Stu
{
	char name[20];
	int age;
	float score;
};

int main()
{
	struct Stu s = { 0 };
	FILE* pf = fopen("test.txt", "rb");
	if (pf == NULL)
	{
		perror("open file for reading");
		return 1;
	}
	//Write file
	fread(&s, sizeof(struct Stu), 1, pf);
	printf("%s\n%d\n%f\n", s.name, s.age, s.score);
	//Close file
	fclose(pf);
	pf = NULL;
	return 0;
}

Random reading and writing of files  

  The sequential read-write function of a file is a function that performs sequential input or output operations on the data in the file. However, if you can only input and output files from front to back in a proper manner, it will be more clumsy. In order to input and output files more flexibly, there are file operation functions that can read and write files randomly.

fseek function  

  Function prototype: int fseek (file * stream, long, int offset, int origin);

Function: locate the file position pointer according to the position and offset of the file position pointer

Parameter: the first parameter is the file pointer; The second parameter is the offset relative to "a position", in bytes; The third parameter is "somewhere"

  Before using this function, you need to understand the process of sequential reading and writing in the file

#include<stdio.h>

int main() {
	FILE* fp = fopen("test.txt", "r");
	if (fp == NULL) {
		perror("open file for writting");
		return 1;
	}
	char arr[30] = { 0 };
	for (int i = 0; i < 7; i++) {
		arr[i] = fgetc(fp);
	}
	
	//Close file
	fclose(fp);
	fp = NULL;
	return 0;
}

 

  Every time fgetc is performed, the system will record the last read position. The position marked is called the file position pointer,

The random read and write operation of the file is realized by moving the file position pointer

fseek locates the file position pointer according to the position and offset of the file position pointer   of

The third parameter in fseek can be specified with a system supplied macro  

origin:
         SEEK_CUR     Current position of file pointer
         SEEK_END     The End of file
         SEEK_SET     Beginning of file   Where the file starts

#include<stdio.h>

int main(){
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		return 1;
	}
	fputs("ABCDEFG", pf);
	fseek(pf, 4, SEEK_SET);//Move the file position pointer 4 bytes to the right at the beginning of the file
	char a = fgetc(pf);//a is E, and the file position pointer is at F after calling fgetc function
	fseek(pf, -4, SEEK_CUR);//Move the file position pointer 4 bytes to the left from the current position
	char c = fgetc(pf);//C is B, and the file position pointer is at C after calling fgetc function

	int ret = ftell(pf);//At this time, the offset of the file position pointer from the file start position is 2
	printf("a=%c\n", a);
	printf("b=%c\n", c);
	printf("ret=%d\n", ret);
	fclose(pf);
	pf = NULL;
	return 0;
}

Execution results:

  ftell function

  Function model: long ftell(FILE *stream);

Function: returns the offset of the file position pointer relative to the starting position

The ftell function has been used in the above code, which will not be explained here

remind function  

Functional model:   void rewind(FILE *stream);

Function: move the file position pointer to the starting position of the file

#include<stdio.h>

int main(){
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		return 1;
	}
	fputs("ABCDEFG", pf);
	fseek(pf, 4, SEEK_SET);//Move the file position pointer 4 bytes to the right at the beginning of the file	
	printf("fseek:%d\n", ftell(pf));
	rewind(pf);
	printf("rewind: %d\n", ftell(pf));

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

  Execution results:

  Find the size of a file

#include<stdio.h>

int main(){
	FILE* pf = fopen("test.txt", "w+");
	if (pf == NULL)
	{
		return 1;
	}
	fputs("ABCDEFG", pf);
	fseek(pf, 0, SEEK_END);//Move the file position pointer to the end of the file (the end of the file is after G)
	printf("File size:%d\n", ftell(pf));

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

Execution results:

  The string "ABCDEFG" is eight bytes in size, but why   Is it 7? Because '\ 0' is the end flag of the string, the operating system stops writing when it encounters the end flag of the string after writing ABCDEFG to the file

If you want to put '\ 0' in a file, you can use the fputc function

#include<stdio.h>

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

	fputc('\0', pf);
	fseek(pf, 0, SEEK_END);//Move the file position pointer to the end of the file
	printf("File size:%d\n", ftell(pf));

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

Or so

#include<stdio.h>

int main()
{
	FILE *fp = fopen("text_7_1.txt", "w+");
	if (!fp)
	{
		perror("fopen");
		return 1;
	}
	char frr[5] = "ABCD";
	fwrite(frr, sizeof(char), 5, fp);//Specify length

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

Here's a supplement to the end of the file: you can understand the end of the file as an EOF (end of file identifier)   EOF), once the function reads the EOF, it can know that the valid data of the file has been read, and the EOF naturally does not belong to the valid data. The file size here refers to the number of bytes of valid data of the file, which means that even an empty file has a size. For example, the creation date and modification date of the file are recorded, but these data do not belong to the "valid data" entered by the user.

 

File decision function

  ferror function

  Function template: int ferror(FILE *stream);

Function: determine whether there is an error during file reading

Return value: 0 is returned if there is no error, and non-zero value is returned if there is an error

  feof function

Function template: int feof(FILE *stream);

Function: determine whether to read to the end of the file at the end of the file reading operation

Return value: 0 is returned if the end of the file is not read at the end of the file reading operation. A non-zero value is returned if the end of the file is read

#include<stdio.h>

int main()
{
	FILE *fp = fopen("text_7_1.txt", "w+");
	if (!fp)
	{
		perror("fopen");
		return 1;
	}
	char frr[50] = "ABCD";
	char tmp[40] = { 0 };
	fwrite(frr, sizeof(char), 5, fp);
	rewind(fp);
	fgets(tmp, 20, fp);
	if (!ferror(fp))
	{
		printf("Successfully deposited\n");
	}
	if (feof(fp))	
	{
		printf("It's at the end of the file\n");
	}
	fclose(fp);
	fp = NULL;
	return 0;
}

Topics: C++ C# Algorithm