C language file operation (super detailed)

foreword

This article mainly introduces the relevant content of file operation in C language (for example: file reading, writing and other related functions).

1. What is a document

A file is a collection of information stored on a computer with a computer hard disk as a carrier. It is a kind of data source, and its main function is to save data.

Putting data into files, compared with the data on the stack in the code program, has the advantage that it can be added when needed and deleted when discarded at any time, and the data can be persisted.

In programming, we generally talk about two types of files: program files and data files (classified from the perspective of file functions).

1.1 Program files

Including source program files (suffix .c), object files (windows environment suffix .obj), executable programs (windows environment suffix .exe), etc.

1.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 the file from which the program needs to read data, or the file that outputs the content.

1.3 File name

The file name is the identification of the existence of the file, and the operating system controls and manages it according to the file name. Each file is assigned a specific name consisting of the file's main name and extension.

A file must have a unique file identifier for user identification and reference.

The file name consists of 3 parts: file path + file name trunk + file suffix .
For example: c:\code\test.txt

2. Opening and closing of files

2.1 File Pointer

In the cache file system, the key concept is "file type pointer", referred to as "file pointer".
Each used file has opened up a corresponding file information area in the memory, which is used to store the relevant information of the file (such as the name of the file
, the status of the file and the 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 VS 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;
};

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 FILE structure according to the situation of the file, and fill it with information, and the user does not need to care about the details.
Generally, the variables of this FILE structure are maintained through a FILE pointer, which is more convenient to use.

Below we can create a FILE* pointer variable:

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

Definition pf is 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. That is to say, the file associated with it can be found through the file pointer variable.

2.2 Opening and closing of files

Files should be opened before reading and writing, and should be closed after use.

When writing a program, when opening a file, a FILE* pointer variable will be returned to point to the file, which is equivalent to establishing the relationship between the pointer and the file.

ANSIC stipulates that the fopen function is used to open the file, and the fclose is used to close the file.

//打开文件
FILE* fopen(const char* filename, const char* mode);
//关闭文件
int fclose(FILE* stream);

Open as follows:

file usage meaning If the specified file does not exist
"r" (read-only) To enter data, open an existing text file go wrong
"w" (write only) To output data, open a text file create a new file
“a” (append) Add data to the end of the text file create a new file
"rb" (read-only) To enter data, open a binary file go wrong
"wb" (write only) To output data, open a binary file create a new file
“ab” (append) append data to the end of a binary file go wrong
"r+" (read and write) Open a text file for reading and writing go wrong
"w+" (read and write) For reading and writing, suggest a new file create a new file
"a+" (read and write) Open a file for reading and writing at the end of the file create a new file
"rb+" (read and write) Open a binary file for reading and writing go wrong
"wb+" (read and write) Create a new binary file for reading and writing create a new file
"ab+" (read and write) Open a binary file for reading and writing at the end of the file create a new file

Example code:

/* fopen fclose example */
#include <stdio.h>
int main()
{FILE* pFile;//打开文件pFile = fopen("myfile.txt", "w");//文件操作if (pFile != NULL){fputs("fopen example", pFile);//关闭文件fclose(pFile);}return 0;
}

3. Sequential reading and writing of files

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
binary input fread document
binary output fwrite document

3.1 fputc

int fputc(int char, FILE *stream)

illustrate

Write the character specified by the parameter  char  (an unsigned character) into the specified stream stream, and move the position identifier forward.

parameter

  • char  - This is the character to be written. The character is passed with its corresponding int value.
  • stream  - This is a pointer to a FILE object identifying the stream to which characters are to be written.

return value

If no error occurred, the character that was written is returned. If an error occurs, EOF is returned, and the error identifier is set.

//pf指向文件
fputc('a', pf);

3.2 fgetc

int fgetc(FILE *stream)

illustrate

Gets the next character (an unsigned char) from the specified stream and advances the position identifier.

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream on which to perform the operation.

return value

The function returns the character read as an unsigned char cast to an int, or EOF if end-of-file is reached or a read error occurs.

//pf指向的文件中有abcdefg
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

3.3 fputs

int fputs(const char *str, FILE *stream)

illustrate

Writes the string to the specified stream, excluding the null character.

parameter

  • str  – This is an array containing the null-terminated sequence of characters to be written.
  • stream  - This is a pointer to a FILE object identifying the stream to which the string is to be written.

return value

The function returns a non-negative value, or EOF if an error occurs.

//pf指向文件
fputs("hello world", pf);

Note: If the file is opened in the form of "w", using the fputs function will overwrite the original data.

3.4 fgets

char *fgets(char *str, int n, FILE *stream)

illustrate

Reads a line from the specified stream and stores it in the string pointed to by str. It stops when (n-1) characters have been read, or a newline character has been read, or the end of the file has been reached.

parameter

  • str  – This is a pointer to a character array that stores the string to be read.
  • n  – This is the maximum number of characters to read (including the final null character). Usually the length of the array passed as str is used.
  • stream  – This is a pointer to a FILE object that identifies the stream from which characters are to be read.

return value

If successful, the function returns the same str parameter. If the end of the file is reached or no characters are read, the contents of str are unchanged and a null pointer is returned.

If an error occurs, returns a null pointer.

//pf指向的文件中有hello world
//定义一个数组
char arr[10] = { 0 };
fgets(arr, 5, pf);    //将所读取的数据放入arr中
printf("%s\n", arr);	//输出hell

3.5 fprintf

int fprintf(FILE *stream, const char *format, ...)

illustrate

Send formatted output to stream.

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream.
  • format  - This is the C string containing the text to be written to stream.
  • Additional parameters  – Depending on the format string, the function may require a series of additional parameters, each containing a value to be inserted, replacing each % tag specified in the format parameter. The number of parameters should be the same as the number of % labels.

return value

Returns the total number of characters written if successful, otherwise returns a negative number.

#include<stdio.h>typedef struct S
{char name[10];int age;}Peo;int main()
{//打开文件FILE* pf = fopen("test.txt", "w");if (pf != NULL){//写入文件Peo p = { "zhangsan", 18 };fprintf(pf, "%s %d\n", p.name, p.age);//关闭文件fclose(pf);pf = NULL;}return 0;
}

3.6 fscanf

int fscanf(FILE *stream, const char *format, ...)

illustrate

Read formatted input from stream.

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream.
  • format  – This is a C string containing one or more of: space characters, non-space characters  , and  the format specifier .
  • Additional parameters  – Depending on the format string, the function may require a series of additional parameters, each containing a value to be inserted, replacing each % tag specified in the format parameter. The number of parameters should be the same as the number of % labels.

return value

If successful, the function returns the number of successful matches and assignments. If the end of the file is reached or a read error occurs, EOF is returned.

#include<stdio.h>typedef struct S
{char name[10];int age;}Peo;int main()
{//打开文件FILE* pf = fopen("test.txt", "r");if (pf != NULL){//读取文件Peo p = { 0 };fscanf(pf, "%s %d", p.name, &p.age);printf("%s %d", p.name, p.age);//关闭文件fclose(pf);pf = NULL;}return 0;
}

3.7 fwrite

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

illustrate

Writes   the data in the array pointed to by  ptr to the given stream stream  .

parameter

  • ptr  – This is the pointer to the array of elements to be written.
  • size  – This is the size, in bytes, of each element to be written.
  • nmemb  – This is the number of elements, each of size bytes.
  • stream  – This is a pointer to a FILE object specifying an output stream.

return value

If successful, the function returns a size_t object representing the total number of elements, which is an integer data type. If this number differs from the nmemb parameter, an error is displayed.

#include<stdio.h>typedef struct S
{char name[10];int age;}Peo;int main()
{//打开文件FILE* pf = fopen("test.txt", "wb+");if (pf != NULL){//写入文件Peo p = { "lisi", 19 };fwrite(&p, sizeof(Peo), 1, pf);//关闭文件fclose(pf);pf = NULL;}return 0;
}

3.8 fread

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

illustrate

 Read data  from the given  stream into  the array pointed to by ptr .

parameter

  • ptr  - This is a pointer to a block of memory with a minimum size  size*nmemb  bytes.
  • size  – This is the size, in bytes, of each element to be read.
  • nmemb  – This is the number of elements, each of size bytes.
  • stream  – This is a pointer to a FILE object specifying an input stream.

return value

The total number of elements successfully read is returned as a size_t object, which is an integer data type. If the total differs from the nmemb parameter, an error may have occurred or the end of the file may have been reached.

#include<stdio.h>typedef struct S
{char name[10];int age;}Peo;int main()
{//打开文件FILE* pf = fopen("test.txt", "rb+");if (pf != NULL){//读取文件Peo p = { 0 };fread(&p, sizeof(Peo), 1, pf);printf("%s %d\n", p.name, p.age);//关闭文件fclose(pf);pf = NULL;}return 0;
}

3.9 sscanf, sprintf function

  • sscanf function
int sscanf(const char *str, const char *format, ...)

illustrate

Read formatted input from a string.

parameter

  • str  – This is the C string that is the source of data retrieved by the function.
  • format  – This is a C string containing one or more of: space characters, non-space characters  , and  the format specifier .
  • Additional Parameters  – This function accepts a series of pointers as additional parameters, each pointer to an object, the object type is specified by the corresponding % label in the format string, the parameters are in the same order as the % labels.

return value

If successful, the function returns the number of successful matches and assignments. If the end of the file is reached or a read error occurs, EOF is returned.

#include<stdio.h>typedef struct S
{char name[10];int age;}Peo;int main()
{//定义一个字符串char buffer[] = { "zhansan 19" };//定义一个结构但不赋值Peo p = { 0 };sscanf(buffer, "%s %d", p.name, &p.age);printf("%s %d", p.name, p.age);    //zhangsan 19return 0;
}
  • sprintf function
int sprintf(char *str, const char *format, ...)

illustrate

Send formatted output to   the string pointed to by str .

parameter

  • str  – This is a pointer to a character array that stores C strings.
  • format  - This is the string containing the text to be written to the string str. It can contain embedded format tags, which can be replaced by values ​​specified in subsequent additional parameters, and formatted as desired.
  • Additional parameters  – Depending on the format string, the function may require a series of additional parameters, each containing a value to be inserted, replacing each % tag specified in the format parameter. The number of parameters should be the same as the number of % labels.

return value

If successful, returns the total number of characters written, excluding the null character appended to the end of the string. On failure, a negative number is returned.

#include<stdio.h>typedef struct S
{char name[10];int age;}Peo;int main()
{//定义一个结构Peo p = { "zhangsan",19 };//定义一个字符串char buffer[50] = { 0 };sprintf(buffer, "%s %d\n", p.name, p.age);printf("%s", buffer);    //zangsan 19return 0;
}

3.10 Comparing a set of functions

scanf/fscanf/sscanf
printf/fprintf/sprintf

How are these functions different?

  • scanf formatted input function for the standard input stream (stdin)

  • printf Formatted output function for the standard output stream (stdout)

  • fscanf formatted input function for all input streams (filestream/stdin)

  • fprintf formatted output function for all output streams (filestream/stdout)

  • sscanf converts a string to formatted data

  • sprintf converts formatted data into a string

4. Random reading and writing of files

4.1 fseek

int fseek(FILE *stream, long int offset, int whence)

illustrate

Set the file position of the stream  stream  to the given offset  offset , the parameter offset means  the number of bytes to look for from the given  whence position.

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream.
  • offset  – This is the offset relative to whence, in bytes.
  • whence  – This is where to start adding the offset. It is generally specified as one of the following constants:
constant describe
SEEK_SET beginning of file
SEEK_CUR current position of the file pointer
SEEK_END end of file

return value

The function returns zero if successful, otherwise a non-zero value.

/* fseek example */
#include <stdio.h>
int main()
{FILE* pFile;pFile = fopen("example.txt", "wb");fputs("This is an apple.", pFile);fseek(pFile, 9, SEEK_SET);fputs(" sam", pFile);    //文件内容被改为This is a sample.fclose(pFile);return 0;
}

4.2 ftell

long int ftell(FILE *stream)

illustrate

Returns the offset of the given stream relative to the starting position

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream.

return value

This function returns the current value of the location identifier. If an error occurs, -1L is returned and the global variable errno is set to a positive value.

/* ftell example : getting size of a file */
#include <stdio.h>
int main()
{FILE* pFile;long size;pFile = fopen("myfile.txt", "rb");if (pFile == NULL) perror("Error opening file");else{fseek(pFile, 0, SEEK_END); // non-portablesize = ftell(pFile);fclose(pFile);printf("Size of myfile.txt: %ld bytes.\n", size);}return 0;
}

4.3 rewind

void rewind(FILE *stream)

illustrate

Sets the file position to the beginning of the file for the given  stream  .

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream.

return value

none

/* rewind example */
#include <stdio.h>
int main()
{int n;FILE* pFile;char buffer[27];pFile = fopen("myfile.txt", "w+");for (n = 'A'; n <= 'Z'; n++)fputc(n, pFile);rewind(pFile);fread(buffer, 1, 26, pFile);fclose(pFile);buffer[26] = '\0';puts(buffer);return 0;
}

5. Text files and binary files

Depending on how the data is organized, data files are called text files or binary files .

Data is stored in binary form in memory, and if it is output to external storage without conversion, it is a binary file . If it is required to store in the form of ASCII code on the external storage, it needs to be converted before storage. A file stored in the form of ASCII characters is a text file .

How is a piece of data stored in memory?

Characters are all stored in ASCII form, and numeric data can be stored in either ASCII or binary form.
If there is an integer 10000, if it is output to the disk in the form of ASCII code, it will occupy 5 bytes on the disk (one byte for each character), and output in binary form, it will only occupy 4 bytes on the disk (VS test ).

test code

#include <stdio.h>
int main()
{int a = 10000;FILE* pf = fopen("test.txt", "wb");fwrite(&a, 4, 1, pf);//二进制的形式写到文件中fclose(pf);pf = NULL;return 0;
}

6. Judgment of the end of file reading

feof function

int feof(FILE *stream)

illustrate

Tests for the end-of-file identifier of the given stream stream.

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream.

return value

The function returns a nonzero value when the end-of-file identifier associated with the stream is set, and zero otherwise.

ferror function

int ferror(FILE *stream)

illustrate

Test the error identifier for the given stream stream.

parameter

  • stream  – This is a pointer to a FILE object that identifies the stream.

return value

The function returns a non-zero value if the error identifier associated with the stream is set, and a zero value otherwise.

Note:

As mentioned earlier, the return of EOF by the fgetc (or getc) function does not necessarily mean the end of the file, and EOF will also be returned when an error occurs while reading the file. That is, the EOF macro can not only indicate the state of reading the end of the file, but also indicate the read and write errors in the I/O operation and the error status of some other associated operations. Obviously, just returning EOF(-1) to consider end-of-file is clearly incorrect.

Because of this, we need to use the feof function to determine the reason for returning EOF. When the feof function returns true, it indicates that the end of the file has been read. Of course, while using the feof function to detect the cause of the end of the file, it is also necessary to use the ferror function to detect whether there is an error in the file reading operation. When the ferror function returns true, it means that there is an error. In the actual program, the ferror function should be used to check whether there is an error every time a file operation is performed.

Keep in mind: during the file reading process, the return value of the feof function cannot be used to directly determine whether the file is over. Instead, it is applied when the file reading ends, judging whether the reading fails to end, or the end of the file is encountered.

There are two situations for the end of file reading: 1. An exception occurs during the reading process; 2. The end of the file is read;
to find out the reason for the end of file reading, it can be divided into the following situations:

  1. After reading the text file, judge whether the return value is EOF ( fgetc ) or NULL ( fgets )

    For example:
    fgetc judges whether it is EOF.
    fgets determines whether the return value is NULL.

  2. After reading the binary file, judge whether the return value is less than the actual number to be read.

    For example:
    fread judges whether the return value is less than the actual number to be read.

For the judgment of reading exceptions, we consider  ferror() the return value of the judgment function:

  1. If ferrror()true - end with abnormal read;
  2. If feof()true - read to the end normally and end;

Examples of text files

#include <stdio.h>
#include <stdlib.h>
int main(void)
{int c; // 注意:int,非char,要求处理EOFFILE* fp = fopen("test.txt", "r");if (!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环{putchar(c);}//判断是什么原因结束的if (ferror(fp))puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);
}

Examples of binary files

#include <stdio.h>
enum { SIZE = 5 };
int main()
{double a[SIZE] = { 1.,2.,3.,4.,5. };FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组if (ret_code == SIZE) {puts("Array read successfully, contents: ");for (int n = 0; n < SIZE; ++n) printf("%f ", b[n]);putchar('\n');}else { // error handlingif (feof(fp))printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {perror("Error reading test.bin");}}fclose(fp);
}

7. 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 creates a "file buffer" in the memory for each file being used in the program. Data output from memory to disk will be sent to the buffer in memory first, and then sent to disk together after the buffer is filled. If data is read from the disk to the computer, the data read from the disk file is input to the memory buffer (full of the buffer), and then the data is sent from the buffer to the program data area (program variables, etc.) one by one. The size of the buffer is determined by the C compilation system.

#include <stdio.h>
#include <windows.h>
int main()
{FILE* pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)//注:fflush 在高版本的VS上不能使用了printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭文件的时候,也会刷新缓冲区pf = NULL;return 0;
}

A conclusion can be drawn here:
because of the existence of the buffer, when the C language operates the file, it needs to refresh the buffer or close the file at the end of the file operation.
Failure to do so can cause problems reading and writing files.

At this point, the content about "File Operation" is over.
Thank you for watching
. It is not easy to create. If it is helpful to you, please click three times.
Your support is the biggest motivation for my creation! ! !

Guess you like

Origin blog.csdn.net/m0_69824302/article/details/130540404