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
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
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.
1. Different C compilers don’t have exactly the same FILE type, but they do.
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.
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
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
#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
There is a data.txt file under the program directory
Data on the desktop
You have to write a complete file name
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
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
Sequential reads and writes to files
Fputc write character function
#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
flow
So what does it mean that it applies to all output streams
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
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
The same applies to all input streams
#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
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
The same applies to all output streams
#include<stdio.h>
int main(a)
{
fputs("hello bit".stdout);
fputs("hello bit\n".stdout);
fputs("hello bit".stdout);
return 0;
}
Copy the code
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
The same applies to all input streams
#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
Fprintf formats the output function
#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
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
Fscanf Formats the input function
#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
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
Fwrite Binary output function
#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
Unfortunately, it only applies to file streams
Fread binary input
#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
Like fwrite, it only applies to file streams
Compare a set of functions
scanf/fscanf/sscanf
sscanf
#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
printf/fprintf/sprintf
sprintf
#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
Random reads and writes to files
fseek
Locates a file pointer based on its position and offset.
#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
ftell
Locates a file pointer based on its position and offset.
int a = ftell(pf);
printf("%d\n", a);
Copy the code
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
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).
Let’s write 10,000 data in binary form to our data file and look at it
#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
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.
- 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.