File operations in c language

Preface

Why do we need file operations? When we write code, the input content is stored in memory, and when the program ends or the power is turned off, the content will also be destroyed. In this way, information cannot be saved, which involves the issue of data persistence. Our general data persistence methods include storing data in disk files, storing data in databases, etc. Using files, we can store data directly on the computer's hard drive, achieving data persistence.

Regarding the relationship between memory and files, the following picture will explain it.
Insert image description here
Let’s learn file operations

1.What is a file

The files on disk are files.
But in programming, we generally talk about two types of files: program files and data files (classified from the perspective of file function).
1.1 Program files

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境
后缀为.exe)。

1.2 Data files

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,
或者输出内容的文件。

Before learning file operations, we all input from the keyboard and then output to the screen. This does not allow data persistence. Now we can write the data to the hard disk, and then save the data in the hard disk. Data is entered into the program. This can also achieve data persistence.
1.3 File name
A file must have a unique file identification to facilitate user identification and reference.
The file name contains 3 parts: file path + file name trunk + file suffix

D:\bite study code\task\task_10_12\text.c
//文件路径:D:\bite study code\task\task_10_12
//文件主干:text
//文件后缀:.c

For convenience, we call the file identifier the file name

2. Opening and closing files

2.1 File pointer
In the buffered file system, the key concept is the "file type pointer", referred to as the "file pointer".
Each used file opens 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
, file status and 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:
in the stdio provided by the VS2013 compilation environment The .h header file has the following file type declaration:

struct _iobuf {
    
    
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
       };
typedef struct _iobuf FILE;

In different compilers, the contents of the FILE structure are also different.
Whenever the user opens a file, the operating system will create the variables of the FILE structure by itself and fill in the contents of the structure. The user does not need to worry about this.
When we want to write something in the file or get something in the file, we only need an address where we can find the file information area, and then use the file information area to access this file.
We create an address (FILE* pointer variable) like this:

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

defines pf as 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. In other words, the file associated with it can be found through the file pointer variable.
For example:
Insert image description here
2.2 Opening and closing of files
The file should be opened before reading and writing, and should be opened after use. Close the file.
When writing a program, when opening a file, a FILE* pointer variable pointing to the file will be returned, which is equivalent to establishing a
pointer and file relationship.
ANSIC stipulates that the fopen function is used to open the file and fclose is used to close the file.

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

Open as follows:
Insert image description here
Example code:

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

Let’s talk about a path issue. When opening a file, const char * filename refers to the name of the file. By default, the file is in the current path of the program. If you put this file on the upper level or above Superior, when we go to access this file, it will show that the file cannot be found.
Path:
1. Relative path

.\\当前路径
..\\上一级路径

Why use \ instead of \because \ means escape in the program
2. Absolute path

D:\\bite study code\\task\\task_10_11\\task_10_11\\data.txt   绝对路径

Code actual column:

#include<stdio.h>
int main()
{
    
    
	//打开文件
	/*FILE* pf=fopen("data.txt", "w");*/
	//相对路径
	//  .\\指当前路径  
	//   ..\\指上一个路径


	/*FILE* pf = fopen(".\\..\\data.txt", "r");*///指当前路径的上一个路径   

	/*FILE* pf = fopen("..\\..\\data.txt", "r");*///指当前路径的上一个路径的上一个路径


	//绝对路径

	FILE* pf = fopen("D:\\bite study code\\task\\task_10_11\\task_10_11\\data.txt", "r");//这个就是从根找,就是绝对路径

	if (pf == NULL)
	{
    
    
		perror("fopen");
		return;
	}
	//写文件



	//关闭文件
	fclose(pf);
	pf = NULL;

	return 0;
}

3. Sequential reading and writing of files

Insert image description here
We divide it into a category:
Character class: character input function (fgetc), character output function (fputc)
Text line (string) : Text line input function (fgets) Text output function (fputs)
Formatting (integer, floating point): Formatted input function (fscanf) Formatted output function (fprintf) a>
Binary: Binary input (fread) Binary output (fwrite)

Before introducing these functions, let us first talk about the concept of stream. The concept of stream itself is an extremely abstract thing. All streams are divided into two types, one is the standard stream and the other is the file stream. .
Standard stream:
1. Standard input stream: stdin (input from keyboard)
2. Standard output stream: stdout( Print on the screen)
File stream:
1. File input stream: read the contents of the file and input them into the memory
2. File output stream: output to a file through an in-memory program

Character class:
Character output function (fputc)

int fputc ( int character, FILE * stream );

int character: The character you need to output to the file from memory. The character here needs to be integer promoted and then converted to an unsigned character internally
FILE * stream: pointer Pointer that identifies the FILE object of the output stream (actually output to the address pointing to the file information area, and then put the content into the file through the information in the file information area)
The return type is: int
If the return is successful, the returned value is the ASCII code value of the character.
If the return fails, the returned value is EOF (-1) to confirm the type returned above.
Code implementation:

#include<stdio.h>
int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "w");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//写文件
	fputc('a', pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Displayed in the file:
Insert image description here
I now need to print 26 letters:

int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "w");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//写文件
	char ch;
	for (ch = 'a'; ch <= 'z'; ch++)
	{
    
    
		fputc(ch, pf);
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Displayed in the file:
Insert image description here
Character output function (fgetc)

int fgetc ( FILE * stream )

FILE * stream: Pointer to the FILE object identifying the input stream (input the contents of the file into memory)
Return type: int
Return value: If the return is successful, the returned character will be integer-raised and then returned to the memory as an ASCII code value.
If the return fails, return EOF
Code implementation:

int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	int ch=fgetc(pf);
	printf("%c", ch);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 

We will print on the screen:
Insert image description here
Text class:
Text output function (fputs)

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

const char * str: The string to be output
FILE * stream: Pointer to the FILE object identifying the output stream
Return type: int
Return value: Return a non-negative value if successful.
Return EOF if failed.
Code implementation:

int main()
{
    
    
	//打开文件
	FILE* pf = fopen("data.txt", "w");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//写文件
	fputs("abcdefg", pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Displayed in the file:
Insert image description here
Text input function (fgets)

char * fgets ( char * str, int num, FILE * stream );

char * str: Pointer to the character array that needs to be copied to the target
int num: The maximum number of characters copied to str (copying will stop when a newline character is encountered, assuming that if the target The maximum character array is 100, but only 99 characters can be copied)
FILE * stream: Pointer to the FILE object identifying the input stream.
Return type: char*
Return value: If the return is successful, the first address of the str array is returned.
If the return fails, a null pointer is returned. (NULL)
Code implementation:

int main()
{
    
    
	char arr[5] = {
    
     0 };
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	//判断是否打开成功
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fgets(arr, 5, pf);
	printf("%s", arr);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Print on the screen:
Insert image description here
If you add a newline character to the file:
Insert image description here
If you encounter a space, you can still print the space:
Insert image description here

Formatting:
Format output function (fprintf)

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

FILE * stream: Pointer to the FILE object identifying the output stream.
const char * format: Compare the description of the printf function
Suppose you want to output an integer data:
printf function printf( "%d",a);
fprintf function fprintf( FILE * stream, "%d", a);
Return type: int
Return value: If successful, the total number of written characters will be returned.
If the return fails, a negative number will be returned.
Code implementation:

struct stu
{
    
    
	char name[20];
	int age;
	float hight;
};
int main()
{
    
    
	 struct stu s = {
    
     "zhangsan",20,175.00 };
	 //打开文件
	 FILE* pf=fopen("data.txt", "w");
	 if (pf == NULL)
	 {
    
    
		 perror("fopen");
	 }
	 //写文件
	 fprintf(pf, "%s-%d-%f", s.name, s.age, s.hight);
	 //关闭文件
	 fclose(pf);
	 pf = NULL;
	return 0;
}

Displayed in the file:
Insert image description here
Format input function (fscanf)

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

FILE * stream: Pointer to a FILE object identifying the input stream from which data is to be read
Return type: int
Code implementation: < /span>

struct stu
{
    
    
	int age;
	float hight;
	char name[20];
};
int main()
{
    
    
	struct stu s = {
    
    0};
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fscanf(pf, "%d-%f-%s", &(s.age), &(s.hight),s.name);
	printf("%s-%d-%f", s.name, s.age, s.hight);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

Print on screen:
Insert image description here
Binary function:
Binary output function (fwrite)

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

const void * ptr: Points to the address of the element array to be written
size_t size: The size of each element that needs to be copied (in bytes)
size_t count: The number of elements to be copied
FILE * stream: Pointer to the FILE object of the specified output stream.
Code implementation:

int main()
{
    
    
	int arr[10] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	//打开文件
	FILE* pwrite = fopen("data.txt", "wb");
	if (pwrite == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fwrite(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pwrite);
	//关闭文件
	fclose(pwrite);
	pwrite = NULL;
	return 0;
}

Look under the file:
Insert image description here
is a string of incomprehensible garbled characters, because it is stored in the file in binary form, although we cannot understand it in the file, But it can be converted into memory and printed on the screen. To convert it into memory, you need a binary input function (fread). Next, we will learn this function.

Binary input function (fread)

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );

void * ptr: Points to the address to be copied to the element array
size_t size: The size of each element to be copied (in bytes)
size_t count: The number of elements to be copied
FILE * stream: Pointer to the FILE object of the specified input stream.
Return type: size_t
Code implementation:

int main()
{
    
    
	int arr[10] = {
    
    0};
	//打开文件
	FILE* fwrite=fopen("data.txt", "rb");
	if (fwrite == NULL)
	{
    
    
		perror("fopen");
	}
	//读文件
	fread(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), fwrite);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	//关闭文件
	fclose(fwrite);
	fwrite = NULL;
	return 0;
}

Print on screen:
Insert image description here

4 Random reading and writing of files

4.1fseek function

int fseek ( FILE * stream, long int offset, int origin );

FILE * stream: Pointer to the FILE object identifying the stream
long int offset: Offset
int origin: The position of the file cursor< /span> Code example: At this time: The file cursor is not the file pointer. The file pointer does not move. It is quite a guide. The file cursor will move, and when that content is accessed, the cursor will point there. SEEK_END End of file SEEK_CUR Current position of file cursor
SEEK_SET Beginning of file



#include<stdio.h>
int main()
{
    
    
	char arr[10] = {
    
     0 };
	//打开文件
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
    
    
		perror("fopen");
	}
	//随机访问文件的内容
	fseek(pf, 2, SEEK_SET);
	//读文件
	fgets(arr, 10, pf);
	printf("%s", arr);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

The set condition is to set the beginning offset of the file at the file cursor to 2
Print on the screen:
Insert image description here
4.2fetll (return to file The offset of the pointer relative to the starting position)

long int ftell ( FILE * stream );

example:

#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-portable
    size=ftell (pFile);
    fclose (pFile);
    printf ("Size of myfile.txt: %ld bytes.\n",size);
 }
  return 0;
}

4.3rewind (return the position of the file pointer to the starting position of the file)

void rewind ( FILE * stream );

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.
The data is stored in binary form in the memory. If it is output to external memory without conversion, it is a binary file.
If it is required to be stored in ASCII code on external storage, it needs to be converted before storage. Files stored in the form of ASCII characters are text files.

6. Determination of the end of file reading

6.1 Incorrectly used feof
Remember: During the file reading process, the return value of the feof function cannot be used to directly determine whether the file is ended.
Instead, it is used when the file reading ends to determine whether the reading fails or the end of the file is encountered.

  1. Whether the text file reading is completed, determine whether the return value is EOF (fgetc), or NULL (fgets)
    For example:
    fgetc determines whether It is EOF.
    fgets determines whether the return value is NULL.
  2. Binary file reading end judgment, judge whether the return value is less than the actual number to be read.
    For example:
    fread determines whether the return value is less than the actual number to be read.
    ####### 7. File cache area

7. File cache area

The ANSIC standard uses a "buffer file system" to process data files. The so-called buffer file system means that the system automatically opens up a "file buffer" in the memory for each file being used in the program. The data output from the memory to the disk will be sent to the buffer in the memory first, and then sent to the disk together after the buffer is filled. If data is read from the disk to the computer, the data is read from the disk file and input into the memory buffer (the buffer is filled), 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.
Insert image description here
A conclusion can be drawn here:
Because of the existence of the buffer, when the C language operates a file, it needs to refresh the buffer or finish the file operation. when closing the file.
If not done, it may cause problems reading and writing files.

End of this chapter…

Guess you like

Origin blog.csdn.net/HD_13/article/details/133807993