C language file operations | File classification, file opening and closing, file reading and writing, file status, file deletion and renaming, file buffer

Insert image description here

Welcome to follow the blogger Mindtechnist or join the [ Linux C/C++/Python Community ] to learn and share Linux, C, C++, Python, Matlab, robot motion control, multi-robot collaboration, intelligent optimization algorithms, filter estimation, and multi-sensor information fusion. Knowledge and technology in machine learning, artificial intelligence and other related fields.



Column: "Proficient in C Language"


Classification of files

Disk files and device files

  • Disk file
    refers to an ordered collection of related data, usually stored on external media (such as disk), and is loaded into memory when used.

  • Device file
    In the operating system, each input and output device connected to the host is regarded as a file, and their input and output are equated to reading and writing disk files.

Classification of disk files

Computer storage is physically binary, so physically all disk files are essentially the same: sequential storage in bytes.
Insert image description here

From the perspective of user or operating system usage (logically), files are divided into:

  • Text file: file based on character encoding
  • Binary file: file based on value encoding

Text files and binary files

text file

  • Based on character encoding, common encodings include ASCII, UNICODE, etc.
  • Generally, you can use a text editor to open it directly.
  • The ASCII storage form (ASCII code) of the number 5678 is:
    00110101 00110110 00110111 00111000

binary file

  • Based on value coding, you can specify what a certain value means based on the specific application.
  • Output the data in the memory to the disk as it is stored in the memory
  • The storage form (binary code) of the number 5678 is: 00010110 00101110

Opening and closing files

file pointer

In C language, a pointer variable is used to point to a file. This pointer is called a file pointer.

typedef struct
{
    
    
	short           level;	//缓冲区"满"或者"空"的程度 
	unsigned        flags;	//文件状态标志 
	char            fd;		//文件描述符
	unsigned char   hold;	//如无缓冲区不读取字符
	short           bsize;	//缓冲区的大小
	unsigned char   *buffer;//数据缓冲区的位置 
	unsigned        ar;	 //指针,当前的指向 
	unsigned        istemp;	//临时文件,指示器
	short           token;	//用于有效性的检查 
}FILE;

FILE is a structure type related to file information defined by the system using typedef. The structure contains information such as file name, file status and current location of the file.

The information declaring the FILE structure type is included in the header file "stdio.h". Generally, a pointer variable pointing to a FILE type variable is set, and then these FILE type variables are referenced through it. Through the file pointer, various operations can be performed on the file it points to.

Insert image description here

There are three special file pointers in C language that are opened by the system by default and can be used directly by users without defining them:

  • stdin: standard input, which defaults to the current terminal (keyboard). The scanf and getchar functions we use obtain data from this terminal by default.
  • stdout: standard output, which defaults to the current terminal (screen). The printf and puts functions we use output information to this terminal by default.
  • stderr: standard error, defaults to the current terminal (screen), the perror function we use defaults to output information to this terminal.

file opening

Any file must be opened before use:

#include <stdio.h>
FILE * fopen(const char * filename, const char * mode);
功能:打开文件
参数:
	filename:需要打开的文件名,根据需要加上路径
	mode:打开文件的模式设置
返回值:
	成功:文件指针
	失败:NULL

Several forms of the first parameter:

	FILE *fp_passwd = NULL;

	//相对路径:
	//打开当前目录passdw文件:源文件(源程序)所在目录
	FILE *fp_passwd = fopen("passwd.txt", "r");
	
	//打开当前目录(test)下passwd.txt文件
	fp_passwd = fopen(". / test / passwd.txt", "r");
	
	//打开当前目录上一级目录(相对当前目录)passwd.txt文件
	fp_passwd = fopen(".. / passwd.txt", "r");
		
	//绝对路径:
	//打开C盘test目录下一个叫passwd.txt文件
	fp_passwd = fopen("c://test//passwd.txt","r");

Several forms of the second parameter (how to open the file):

open mode meaning
r or rb Open a text file in read-only mode (does not create the file, and reports an error if the file does not exist)
w or wb Open the file for writing (clear the file if it exists, create a file if it does not exist)
a or ab Open the file in append mode, add content at the end, or create the file if it does not exist
r+ or rb+ Open the file for reading and writing (does not create a new file)
r+ or rb+ Open the file for reading and writing (does not create a new file)
w+ or wb+ Open the file in a readable and writable manner (clear the file if it exists, create a file if it does not exist)
a+ or ab+ Open the file in add mode, open the file and change the file at the end, create the file if it does not exist

Notice:

  • b means binary mode. b is only valid in Windows. The results of using r and rb in Linux are the same.
  • All text file lines under Unix and Linux end with \n, while all text file lines under Windows end with \r\n.
  • Under the Windows platform, open the file in "text" mode without adding b:
    when reading the file, the system will convert all "\r\n" into "\n";
    when writing the file, the system will "\n" will be converted into "\r\n" for writing;
    if the file is opened in "binary" mode, such conversion will not be performed for reading or writing.
  • Under the Unix/Linux platform, there is no difference between "text" and "binary" modes. "\r\n" is input and output as two characters.
int main(void)
{
    
    
	FILE *fp = NULL;

	// "\\"这样的路径形式,只能在windows使用
	// "/"这样的路径形式,windows和linux平台下都可用,建议使用这种
	// 路径可以是相对路径,也可是绝对路径
	fp = fopen("../test", "w");
	//fp = fopen("..\\test", "w");

	if (fp == NULL) //返回空,说明打开失败
	{
    
    
		//perror()是标准出错打印函数,能打印调用库函数出错原因
		perror("open");
		return -1;
	}

	return 0;
}

file closing

Any file should be closed after use:

  • Open files will occupy memory resources. If they are always opened and not closed, a lot of memory will be consumed.
  • There is a limit to the number of files a process can open at the same time. If the maximum number of files opened at the same time is exceeded, calling fopen again to open the file will fail.
  • If fclose is not explicitly called to close the open file, the operating system will be closed uniformly when the program exits.
#include <stdio.h>
int fclose(FILE * stream);
功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
参数:
	stream:文件指针
返回值:
	成功:0
	失败:-1

	FILE * fp = NULL;
	fp = fopen("abc.txt", "r");
	fclose(fp);

Sequential reading and writing of files

Read and write files fgetc and fputc according to characters

write file

#include <stdio.h>
int fputc(int ch, FILE * stream);
功能:将ch转换为unsigned char后写入stream指定的文件中
参数:
	ch:需要写入文件的字符
	stream:文件指针
返回值:
	成功:成功写入文件的字符
	失败:返回-1
char buf[] = "this is a test for fputc";
int i = 0;
int n = strlen(buf);
for (i = 0; i < n; i++)
{
    
    
	//往文件fp写入字符buf[i]
	int ch = fputc(buf[i], fp);
	printf("ch = %c\n", ch);
}

End of file
In C language, EOF represents the end of file (end of file). In the while loop, EOF is used as the end-of-file mark. The file with EOF as the end-of-file mark must be a text file. In text files, data is stored in the form of character ASCII code values. We know that the range of ASCII code values ​​is 0~127, and -1 is impossible, so EOF can be used as the end of file mark.

#define EOF     (-1)

When data is stored in a file in binary form, a -1 value will appear, so EOF cannot be used as the end mark of a binary file. To solve this problem, ANSI C provides a feof function to determine whether the file has ended. The feof function can be used to judge both binary files and text files.

#include <stdio.h>
int feof(FILE * stream);
功能:检测是否读取到了文件结尾。判断的是最后一次“读操作的内容”,不是当前位置内容(上一个内容)
参数:
	stream:文件指针
返回值:0值:已经到文件结尾
	0:没有到文件结尾

read file

#include <stdio.h>
int fgetc(FILE * stream);
功能:从stream指定的文件中读取一个字符
参数:
	stream:文件指针
返回值:
	成功:返回读取到的字符
	失败:-1
char ch;
#if 0
while ((ch = fgetc(fp)) != EOF)
{
    
    
	printf("%c", ch);
}
printf("\n");
#endif

while (!feof(fp)) //文件没有结束,则执行循环
{
    
    
	ch = fgetc(fp);
	printf("%c", ch);
}
printf("\n");

Read and write files fgets, fputs by line

write file

#include <stdio.h>
int fputs(const char * str, FILE * stream);
功能:将str所指定的字符串写入到stream指定的文件中,字符串结束符 '\0'  不写入文件。 
参数:
	str:字符串
	stream:文件指针
返回值:
	成功:0
	失败:-1
char *buf[] = {
    
     "123456\n", "bbbbbbbbbb\n", "ccccccccccc\n" };
int i = 0;
int n = 3;
for (i = 0; i < n; i++)
{
    
    
	int len = fputs(buf[i], fp);
	printf("len = %d\n", len);
}

read file

#include <stdio.h>
char * fgets(char * str, int size, FILE * stream);
功能:从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 '\0' 作为字符串结束。
参数:
	str:字符串
	size:指定最大读取字符串的长度(size - 1
	stream:文件指针
返回值:
	成功:成功读取的字符串
	读到文件尾或出错: NULL
char buf[100] = 0;

while (!feof(fp)) //文件没有结束
{
    
    
	memset(buf, 0, sizeof(buf));
	char *p = fgets(buf, sizeof(buf), fp);
	if (p != NULL)
	{
    
    
		printf("buf = %s", buf);
	}
}

According to the format file fprintf, fscanf

write file

#include <stdio.h>
int fprintf(FILE * stream, const char * format, ...);
功能:根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符 '\0'  为止。
参数:
	stream:已经打开的文件
	format:字符串格式,用法和printf()一样
返回值:
	成功:实际写入文件的字符个数
	失败:-1
fprintf(fp, "%d %d %d\n", 1, 2, 3);

read file

#include <stdio.h>
int fscanf(FILE * stream, const char * format, ...);
功能:从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
参数:
	stream:已经打开的文件
	format:字符串格式,用法和scanf()一样
返回值:
	成功:参数数目,成功转换的值的个数
	失败: - 1
int a = 0;
int b = 0;
int c = 0;
fscanf(fp, "%d %d %d\n", &a, &b, &c);
printf("a = %d, b = %d, c = %d\n", a, b, c);

Read and write files fread and fwrite in blocks

write file

#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:以数据块的方式给文件写入内容
参数:
	ptr:准备写入文件数据的地址
	size: size_tunsigned int类型,此参数指定写入文件内容的块数据大小
	nmemb:写入文件的块数,写入文件数据总大小为:size * nmemb
	stream:已经打开的文件指针
返回值:
	成功:实际成功写入文件数据的块数目,此值和nmemb相等
	失败:0
typedef struct Stu
{
    
    
	char name[50];
	int id;
}Stu;

Stu s[3];
int i = 0;
for (i = 0; i < 3; i++)
{
    
    
	sprintf(s[i].name, "stu%d%d%d", i, i, i);
	s[i].id = i + 1;
}

int ret = fwrite(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);

read file

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:以数据块的方式从文件中读取内容
参数:
	ptr:存放读取出来数据的内存空间
	size: size_tunsigned int类型,此参数指定读取文件内容的块数据大小
	nmemb:读取文件的块数,读取文件数据总大小为:size * nmemb
	stream:已经打开的文件指针
返回值:
	成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。
	失败:0
typedef struct Stu
{
    
    
	char name[50];
	int id;
}Stu;

Stu s[3];
int ret = fread(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);

int i = 0;
for (i = 0; i < 3; i++)
{
    
    
	printf("s = %s, %d\n", s[i].name, s[i].id);
}

Random reading and writing of files

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
功能:移动文件流(文件光标)的读写位置。
参数:
	stream:已经打开的文件指针
	offset:根据whence来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于whence往右移动,如果是负数,则相对于whence往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸。
	whence:其取值如下:
		SEEK_SET:从文件开头移动offset个字节
		SEEK_CUR:从当前位置移动offset个字节
		SEEK_END:从文件末尾移动offset个字节
返回值:
	成功:0
	失败:-1

#include <stdio.h>
long ftell(FILE *stream);
功能:获取文件流(文件光标)的读写位置。
参数:
	stream:已经打开的文件指针
返回值:
	成功:当前文件流(文件光标)的读写位置
	失败:-1

#include <stdio.h>
void rewind(FILE *stream);
功能:把文件流(文件光标)的读写位置移动到文件开头。
参数:
	stream:已经打开的文件指针
返回值:
	无返回值
typedef struct Stu
{
    
    
	char name[50];
	int id;
}Stu;

//假如已经往文件写入3个结构体
//fwrite(s, sizeof(Stu), 3, fp);

Stu s[3];
Stu tmp; 
int ret = 0;

//文件光标读写位置从开头往右移动2个结构体的位置
fseek(fp, 2 * sizeof(Stu), SEEK_SET);

//读第3个结构体
ret = fread(&tmp, sizeof(Stu), 1, fp);
if (ret == 1)
{
    
    
	printf("[tmp]%s, %d\n", tmp.name, tmp.id);
}

//把文件光标移动到文件开头
//fseek(fp, 0, SEEK_SET);
rewind(fp);

ret = fread(s, sizeof(Stu), 3, fp);
printf("ret = %d\n", ret);

int i = 0;
for (i = 0; i < 3; i++)
{
    
    
	printf("s === %s, %d\n", s[i].name, s[i].id);
}

The difference between Windows and Linux text files

  • b means binary mode. b is only valid in Windows. The results of using r and rb in Linux are the same.
  • All text file lines under Unix and Linux end with \n, while all text file lines under Windows end with \r\n.
  • Under the Windows platform, open the file in "text" mode without adding b:
    when reading the file, the system will convert all "\r\n" into "\n";
    when writing the file, the system will "\n" will be converted into "\r\n" for writing;
    if the file is opened in "binary" mode, such conversion will not be performed for reading or writing.
  • Under the Unix/Linux platform, there is no difference between "text" and "binary" modes. "\r\n" is input and output as two characters.

Determine whether a text file is in Linux format or Windows format:

#include<stdio.h>

int main(int argc, char **args)
{
    
    
	if (argc < 2)
		return 0;

	FILE *p = fopen(args[1], "rb");
	if (!p)
		return 0;

	char a[1024] = {
    
     0 };
	fgets(a, sizeof(a), p);

	int len = 0;
	while (a[len])
	{
    
    
		if (a[len] == '\n')
		{
    
    
			if (a[len - 1] == '\r')
			{
    
    
				printf("windows file\n");
			}
			else
			{
    
    
				printf("linux file\n");
			}
		}
		len++;
	}

	fclose(p);

	return 0;
}

Get file status

#include <sys/types.h>
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
功能:获取文件状态信息
参数:
path:文件名
buf:保存文件信息的结构体
返回值:
成功:0
失败-1
struct stat {
    
    
	dev_t         st_dev;         //文件的设备编号
	ino_t         st_ino;          //节点
	mode_t        st_mode;   //文件的类型和存取的权限
	nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
	uid_t         st_uid;         //用户ID
	gid_t         st_gid;         //组ID
	dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
	off_t         st_size;        //文件字节数(文件大小)
	unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
	unsigned long st_blocks;    //块数
	time_t        st_atime;     //最后一次访问时间
	time_t        st_mtime;    //最后一次修改时间
	time_t        st_ctime;     //最后一次改变时间(指属性)
};
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>

int main(int argc, char **args)
{
    
    
	if (argc < 2)
		return 0;

	struct stat st = {
    
     0 };

	stat(args[1], &st);
	int size = st.st_size;//得到结构体中的成员变量
	printf("%d\n", size);
	return 0;
}

Delete files, rename files

#include <stdio.h>
int remove(const char *pathname);
功能:删除文件
参数:
	pathname:文件名
返回值:
	成功:0
	失败:-1

#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
功能:把oldpath的文件名改为newpath
参数:
oldpath:旧文件名
newpath:新文件名
返回值:
成功:0
失败: - 1

file buffer

file buffer

The ANSI C standard uses a "buffered file system" to handle data files.

The so-called buffered file system means that the system automatically opens a file buffer in the memory area for each file being used in the program. Data output from memory to disk must first be sent to the buffer in memory, and then sent together when the buffer is full. to disk.

If data is read from the disk to the computer, a batch of data is input from the disk file into the memory buffer at a time (filling the buffer), and then the data is sent from the buffer to the program data area (to the program variables) one by one.

Disk file access

Insert image description here

  • Disk files are generally stored in disk devices such as hard disks and USB flash drives that are not lost when power is lost, and can be transferred into memory when needed.
  • After editing the file in memory, save it to disk.
  • The interaction between the program and the disk is not completed immediately. The system or program can set buffers as needed to improve access efficiency.

update buffer

#include <stdio.h>
int fflush(FILE *stream);
功能:更新缓冲区,让缓冲区的数据立马写到文件中。
参数:
stream:文件指针
返回值:
成功:0
失败:-1

Insert image description here
Insert image description here


Guess you like

Origin blog.csdn.net/qq_43471489/article/details/134646288