This is the 28th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021.”

File operations

What is a file

  • Files on disk are files
  • But in programming, we generally talk about two kinds of files: program files and data files (classified from the point of view of file function).

Program files

The files include source program files with the extension of.c, object files with the extension of.obj in Windows, and executable files with the extension of.exe in Windows.

The data file

The contents of a file are not necessarily the program, but the data that the program reads and writes when it runs, such as the data file from which the program reads or outputs content

image-20210927131350241


The input and output of the data processed in the past are based on the terminal as the object, that is, input data from the keyboard of the terminal, and the running results are displayed on the display. In fact, sometimes we can output the information to the disk, and then read the data from the disk to the memory when needed. What we deal with here is the file on the disk

The file name

A file should have a unique file id for users to identify and reference

A file name consists of three parts: file path + file trunk + file suffix

image-20210920154954187


File opening and closing

The file pointer

In buffered file systems, the key concept is the “file type pointer”, or ** file pointer **.

Each used file has a corresponding file information area in memory, which is used to store the relevant information of the file (such as file name, file status, file current location, etc.). This information is stored in a structure variable. This structure type is declared by the system and is named FILE.

image-20210927140127421


1. Different C compilers don’t have exactly the same FILE type, but they do.

image-20210927140347390


2. 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. Users do not need to care about details.

3. Generally, a pointer to FILE is used to maintain the variables of the FILE structure, which is more convenient to use.

// We can create a pointer to FILE*
FILE* pf;// File pointer variable
Copy the code

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 (which is a structure variable). The file is accessible through the information in the file information area. That is, the file associated with a file pointer variable can be found.

image-20210927141717048


File opening and closing

Files should be opened before reading and writing, and closed after use. When writing the program, when opening the FILE, it will return a pointer variable of FILE* to point to the FILE, which is equivalent to establishing the relationship between the pointer and the FILE.

ANSIC specifies the use of the fopen function to open the file and fclose to close the file

// Open the file
FILE* fopen(const char* filename,const char* mode);
// Close the file
int fclose(FILE* stream)
Copy the code
image-20210927143044457


Open the way
File Usage meaning If the specified file does not exist
“R” (read only) ** To enter data, open an existing text file ** error
** “w” (just write) ** To output data, open a text file ** Create a new file
** “a” (appended) ** ** Adds data ** to the end of the 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” (additional) Adds data to the end of a binary file error
“R +” (reading and writing) To read and write, open a text file error
“W +” (reading and writing) A new file is recommended for reading and writing Create a new file
“A +” (reading and writing) 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) To read and write, create a new binary file Create a new file
“Ab +” (reading and writing) Open a binary file and read and write at the end of the file Create a new file

We mainly use the first three

image-20210927150002640


image-20210927150925101


#include<stdio.h>

int main(a)
{
	// Open the file
	FILE* pf = fopen("data.txt"."r");
	if (pf == NULL)
	{
		printf("Failed to open.\n");
		perror("fopen");// Print the error message after fopen:
		return 0;
	}
	/ / read the file
	else
	{
		printf("Opened successfully \n");
		// Close the file
		fclose(pf);
		pf = NULL;
	}	
		return 0;
}
Copy the code
There is no data.txt file under the program directory
image-20210927151710788


There is a data.txt file under the program directory
image-20210927152010218


Data on the desktop
image-20210927152650915


You have to write a complete file name

image-20210927153228625


Same thing with writing a file

If you look at the opening method above, you can see that no file will create a new file. Let’s try it on the desktop

#include<stdio.h>

int main(a)
{
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."w");
	if (pf == NULL)
	{
		printf("Failed to open.\n");
		perror("fopen");// Print the error message after fopen:
		return 0;
	}
	/ / write file
	else
	{
		printf("Opened successfully \n");
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210927154402456


Note that this W is not just for anyone

If there is content in the existing file, W destroys all the content in the file, leaving a blank file

image-20210927155758744


Sequential reads and writes to files

image-20210927160334190


Fputc write character function

image-20210927202304278


#include<stdio.h>

int main(a)
{
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."w");
	if (pf == NULL)
	{
		printf("Failed to open.\n");
		perror("fopen");// Print the error message after fopen:
		return 0;
	}
	/ / write file
	else
	{
		fputc('b', pf);
		fputc('i', pf);
		fputc('t', pf);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210927162749323


flow

image-20210927165823966


image-20210927170418132


So what does it mean that it applies to all output streams

image-20210927170532790


Because it can not only print to a file, it can print to a screen

#include<stdio.h>

int main(a)
{
	fputc('b'.stdout);
	fputc('i'.stdout);
	fputc('t'.stdout);
	return 0;
}
Copy the code
image-20210927171118486


Fgetc Read character function

#include<stdio.h>
int main(a)
{
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."r");
	if (pf == NULL)
	{
		perror("fopen");
	}
	else
	{
		/ / read the file
		int ch = fgetc(pf);
		printf("%c",ch);
		ch = fgetc(pf);
		printf("%c", ch);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210927180055768


The same applies to all input streams

image-20210927180439618


#include<stdio.h>

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

	return 0;
}
Copy the code
image-20210927201044532


Pay attention to

The fputc(‘b’, stdout) function is equivalent to the putchar(‘b’) function

The fgetc(stdin) function is equivalent to getchar

Fputs writes the string function

#include<stdio.h>

int main(a)
{
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."w");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		// Write a line of data
		fputs("hello bit", pf);
		fputs("hello bit\n", pf);
		fputs("hello bit", pf);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210927205018496


The same applies to all output streams
image-20210927204030540


#include<stdio.h>

int main(a)
{
	fputs("hello bit".stdout);
	fputs("hello bit\n".stdout);
	fputs("hello bit".stdout);
	return 0;
}
Copy the code
image-20210927214349880


Fgets reads the string function

#include<stdio.h>

int main(a)
{
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."r");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		// Read a line of data
		char arr[20] = { 0 };
		fgets(arr, 5, pf);
		printf("%s\n",arr);
		fgets(arr, 5, pf);
		printf("%s\n", arr);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210927223709225


The same applies to all input streams
image-20210927223852648


#include<stdio.h>

int main(a)
{
	char arr[20] = { 0 };
	fgets(arr, 5.stdin);
	printf("%s\n", arr);
	fgets(arr, 5.stdin);
	printf("%s\n", arr);
	fgets(arr, 5.stdin);
	printf("%s\n", arr);

	return 0;
}
Copy the code
image-20210927224709150


Fprintf formats the output function

image-20210928070048481


#include<stdio.h>

struct MyStruct
{
	int a;
	double b;
};

int main(a)
{
	struct MyStruct mystruct = { 20 ,3.14 };
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."w");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		/ / write data
		fprintf(pf, "%d %lf", mystruct.a, mystruct.b);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210928071302798


The same applies to all output streams
#include<stdio.h>

struct S
{
	int a;
	double b;
	char c;
};

int main(a)
{
	struct S s = { 10.3.25.'a' };
	fprintf(stdout."%d %lf %c", s.a, s.b, s.c);
	return 0;
}
Copy the code
image-20210928071951383


Fscanf Formats the input function

image-20210928072440768


#include<stdio.h>

struct MyStruct
{
	int a;
	double b;
};

int main(a)
{
	struct MyStruct mystruct = {0};
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."r");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		/ / read the data
		fscanf(pf, "%d%lf", &(mystruct.a), &(mystruct.b));
		printf("%d %lf", mystruct.a, mystruct.b);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210928074336753


The same applies to all input streams
#include<stdio.h>
struct S
{
	int a;
	double b;
};
int main(a)
{
	struct S s = { 0 };
	fscanf(stdin."%d%lf", &(s.a), &(s.b));
	printf("%d %lf", s.a, s.b);
	return 0;
}
Copy the code
image-20210928075049270


Fwrite Binary output function

image-20210928082312323


#include<stdio.h>

struct MyStruct
{
	int a;
	double b;
	char num[20];
};

int main(a)
{
	struct MyStruct mystruct = {20.3.14."zhuzhu"};
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		// Write file - write in binary format
		fwrite(&mystruct, sizeof(struct MyStruct), 1, pf);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210928082816543


Unfortunately, it only applies to file streams
image-20210928082912972


Fread binary input

image-20210928083537933


#include<stdio.h>

struct MyStruct
{
	int a;
	double b;
	char num[20];
};

int main(a)
{
	struct MyStruct mystruct = {0};
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."rb");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		// Read files - read in binary format
		fread(&mystruct, sizeof(struct MyStruct), 1, pf);
		printf("%d %lf %s", mystruct.a, mystruct.b, mystruct.num);
		// Close the file
		fclose(pf);
		pf = NULL;
	}
	return 0;
}
Copy the code
image-20210928084402528


Like fwrite, it only applies to file streams
image-20210928084710001


Compare a set of functions

scanf/fscanf/sscanf

image-20210928093439868


sscanf
image-20210928092028652


#include<stdio.h>

struct MyStruct
{
	int a;
	double b;
	char num[20];
};

int main(a)
{
	char arr[20] = { 0 };
	struct MyStruct mystruct = {20.3.14."zhuzhu"};
	struct MyStruct tmp = { 0 };
	sprintf(arr, "%d %lf %s", mystruct.a, mystruct.b, mystruct.num);
	printf("%s",arr);	
	sscanf(arr, "%d%lf%s", &(tmp.a), &(tmp.b), &(tmp.num));
	printf("\n%d\n%lf\n%s\n", tmp.a, tmp.b, tmp.num);
	return 0;
}
Copy the code
image-20210928093011839


printf/fprintf/sprintf

image-20210928092201832


sprintf
image-20210928092014648


#include<stdio.h>

struct MyStruct
{
	int a;
	double b;
	char num[20];
};

int main(a)
{
	char arr[20] = { 0 };
	struct MyStruct mystruct = {20.3.14."zhuzhu"};
	sprintf(arr, "%d %lf %s", mystruct.a, mystruct.b, mystruct.num);
	printf("%s",arr);	
	return 0;
}
Copy the code
image-20210928091850876


Random reads and writes to files

fseek

Locates a file pointer based on its position and offset.

image-20210928151756202


#include<stdio.h>

int main(a)
{
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."r");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		// Read files randomly
		// The start of the file is offset back by 2
		fseek(pf, 2, SEEK_SET);
		int ch = fgetc(pf);
		printf("%c\n",ch);

		// The file's current pointer moves forward by 2
		fseek(pf, 2 -, SEEK_CUR);
		ch = fgetc(pf);
		printf("%c\n", ch);

	}
	return 0;
}
Copy the code
image-20210928152602313


ftell

Locates a file pointer based on its position and offset.

int a = ftell(pf);
printf("%d\n", a);
Copy the code
image-20210928154051054


rewind

Returns the position of the file pointer to the start of the file

#include<stdio.h>

int main(a)
{
	// Open the file
	FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\data.txt"."r");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		// Read files randomly
		// The start of the file is offset back by 2
		fseek(pf, 2, SEEK_SET);
		int ch = fgetc(pf);
		printf("%c\n",ch);

		// The file's current pointer moves forward by 2
		fseek(pf, 2 -, SEEK_CUR);
		ch = fgetc(pf);
		printf("%c\n", ch);

		int a = ftell(pf);
		printf("%d\n", a);

		rewind(pf);
		ch = fgetc(pf);
		printf("%c\n", ch);
	}
	return 0;
}
Copy the code
image-20210928154709457


Text files and binary files

Data files are called text files or binary files, depending on how the data is organized. Data is stored in memory in binary form, which is a binary file if the output of the conversion is not added to external memory. If you want to store it as ASCII on external memory, you need to convert it before storing it. Files stored as ASCII characters are text files

How is a piece of data stored in memory?

All characters are stored in ASCII format, and numeric data can be stored in EITHER ASCII format or binary format. If the integer 10000 is output to the disk as ASCII code, 5 bytes (one byte for each character) will be occupied on the disk, while output in binary code will occupy only 4 bytes on the disk (VS2013 test).

image-20210928170707226


Let’s write 10,000 data in binary form to our data file and look at it

image-20210928170934248


#include<stdio.h>

int main(a)
{
	int a = 10000;
	FILE* pf = fopen("data.txt"."wb");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	else
	{
		// write a
		fwrite(&a, sizeof(int), 1, pf);
	}
	// Close the file
	fclose(pf);
	pf = NULL;
	return 0;
}
Copy the code

The determination of the end of file reading

fgetc

#include<stdio.h>

int main(a)
{
	int ch = 0;
	FILE* pf = fopen("data.txt"."r");
	if (pf == NULL)
	{
		perror("fopen");
		return 0;
	}
	while((ch = fgetc(pf))! =EOF) {printf("%c ", ch);
	}
	// Close the file
	fclose(pf);
	pf = NULL;
	return 0;
}
Copy the code
image-20210928173952985


Misused feOF

Feof is the end of the file read, and determines whether the end of the file is encountered

Ferror file reading is complete. Check if there is an error and finish reading

Remember: the return value of the feOF function cannot be used to determine the end of a file during file reading. Instead, it is used to determine whether a read fails or an end-of-file is encountered at the end of a file read.

  1. Check whether the text file is finished reading and whether the return value is EOF (fgeTC) or NULL (fgets).

For example, fgeTC checks whether EOF. Fgets checks whether the return value is NULL. 2. Binary end of reading judgment to determine whether the returned value is less than the actual number of reads. For example, fread checks whether the returned value is less than the actual number of reads

File buffer

The ANSIC standard uses a “buffered file system” for processing data files, which means that the system automatically creates a “file buffer” in memory for each file in use in the program. The output data from memory to disk is sent to the buffer in memory first. After the buffer is filled, the data is sent to disk together. If data is read from disk to computer, input is read from disk file into memory buffer (fill buffer), and data is sent from buffer to program data area (program variables, etc.) one by one. The size of the buffer is determined by the C compiler system.

#include <stdio.h>
#include <windows.h>
//VS2013 WIN10 environment test
int main(a)
{
FILE*pf = fopen("test.txt"."w");
fputs("abcdef", pf);// Put the code in the output buffer first
printf("Sleep 10 seconds - write data, open test. TXT file, find no contents \n");
Sleep(10000);
printf("Flush buffer \n");
fflush(pf);// Write the output buffer to a file (disk) only when the buffer is flushed
// Note: Fflush is no longer available on older versions of VS
printf("Sleep for another 10 seconds - at this point, open the test. TXT file again, the file has content \n");
Sleep(10000);
fclose(pf);
// Note: fclose also flushes the buffer when closing the file
pf = NULL;
return 0;
}
Copy the code
One conclusion can be drawn here:

Because of the existence of the buffer, C language needs to refresh the buffer or close the file at the end of the file operation. If you do not do this, problems may occur in reading and writing files

Money is valuable, code is priceless

I really hope to have a sino-US hacker war in 2001, pointing at the United States, code to success, reflect the value.