catalogue
Second argument to fopen function
Sequential reading and writing of files
Sequential read-write function of file
Random reading and writing of files
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.
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.#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; }
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; }