1、理论介绍
1.1、文件应用场景1.2、文件操作原理1.3、文件常用API接口1.4、fopen和open的区别 2、案例介绍
2.1、案例1:基本读写操作2.2、案例2:实现CP指令2.3、案例3:修改配置文件
1、理论介绍 1.1、文件应用场景账单游戏进度配置文件 1.2、文件操作原理
1、文件的读写操作是通过文件描述符来实现的(File descriptor)
文件描述符0代表标准输入
文件描述符1代表标准输出
文件描述符2代表标准出错
所以,在linux下创建文件返回的文件描述符是>=3
2、文件操作过程
文件平时是存放在磁盘的块设备中(静态文件),当调用open打开文件时,内核会创建一个数据结构来指向文件,并且在内存中申请一段内存,内核将静态文件的数据读取到内存中(动态文件),后续文件的读写操作都是基于内存的动态文件来实现,当调用close时,内核会将动态文件的数据同步到磁盘的静态文件中。
这么设计的原因是静态文件是按照块来进行读写的,而动态文件时按字节进行读写的,比较灵活。
1、open
int open(const char *pathname, int flags, mode_t mode);
函数作用:打开一个文件
参数介绍:
pathname:文件路径
flags:文件打开的方式(只读、只写、读写、创建)
mode:文件权限
返回值:文件描述符(fd)
2、close
int close(int fd);
函数作用:关闭一个文件
参数介绍:
fd:文件描述符(fd)
3、read
ssize_t read(int fd, void *buf, size_t count);
函数作用:读取文件
参数介绍:
fd:文件描述符(fd)
buf:文件读取的缓冲区
count:读取的数量
返回值:最终读取到的数量
4、write
ssize_t write(int fd, const void *buf, size_t count);
函数作用:写入文件
参数介绍:
fd:文件描述符(fd)
buf:文件写入的缓冲区
count:写入的数量
返回值:最终写入的数量
5、lseek
off_t lseek(int fd, off_t offset, int whence);
函数作用:文件光标偏移
参数介绍:
fd:文件描述符(fd)
offset:文件光标偏移的量
whence:文件光标偏移的位置
来源:fopen来源于C库函数,open来源于UNIX系统库函数移植性:fopen移植性优于open适用范围:open返回的是文件描述符,而UNIX下一切操作皆为文件,例如网络套接字,当然也包括普通文件。而fopen只适用于普通文件。文件IO层次:open属于低级IO,因为它离内核更近,fopen则属于高级IO缓冲区:fopen有缓冲区,open无缓冲区。缓冲区的作用是,当对文件内容进行读写操作时,首先会在内存中开辟一段"缓冲区",当进行读操作时,会将磁盘文件读取到"缓冲区",等到"缓冲区"满了,再从"缓冲区"内读取数据。当进行写操作时,也会先将磁盘文件写入到"缓冲区",等到"缓冲区"满了,在将"缓冲区"的数据写入到磁盘文件。 2、案例介绍 2.1、案例1:基本读写操作
#include2.2、案例2:实现CP指令#include #include int main() { int fd, write_count,read_count = 0; char read_buf[30] = {0}; char* write_buf = "hello world!n"; fd = open("./hello_file", O_RDWR|O_CREAT,0777); if (fd > 0) { printf("open file successn"); } write_count = write(fd, (void*)write_buf, strlen(write_buf)); printf("write_count = %dn",write_count); lseek(fd, 0, SEEK_SET); read_count = read(fd, read_buf, write_count); printf("read_count = %d, read_buf = %sn",read_count, read_buf); close(fd); return 0; }
实现CP指令的步骤如下:
(1) 打开原文件,读取原文件内容
(2) 创建目标文件,把读取到的内容写入目标文件
#include#include #include #include #include #include #include int main(int argc, char** argv) { int fd_src, fd_des = 0; int file_size = 0; char* read_buf = NULL; if (argc != 3) { printf("param num errorn"); exit(-1); } fd_src = open(argv[1], O_RDWR); if (fd_src < 0) { printf("you enter src file no existn"); exit(-1); } file_size = lseek(fd_src, 0, SEEK_END); lseek(fd_src, 0, SEEK_SET); read_buf = (char*)malloc(sizeof(char) * file_size); memset(read_buf, 0 , sizeof(char) * file_size); read(fd_src, read_buf, file_size); fd_des = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0777); write(fd_des, read_buf, file_size); close(fd_src); close(fd_des); return 0; }
编译步骤:gcc cp_file.c -o cp_file
./cp_file a.txt b.txt
实现修改配置文件的步骤:
1、读取文件内容
2、匹配到要修改的key字段
3、修改对应key字段的value值
#include#include #include #include #include #include #include int main(int argc, char** argv) { int fd = 0; int file_size = 0; char* file_name = NULL; char* key = NULL; char* value = NULL; char* read_buf = NULL; char* search_index = NULL; if (argc != 4) { printf("you input arg num errorn"); exit(-1); } file_name = argv[1]; key = argv[2]; value = argv[3]; fd = open(file_name, O_RDWR); if (fd < 0) { printf("you input file no existn"); } file_size = lseek(fd, 0, SEEK_END); read_buf = (char*)malloc(sizeof(char) * file_size); memset(read_buf, 0 , sizeof(char) * file_size); lseek(fd, 0, SEEK_SET); read(fd, read_buf, file_size); search_index = strstr(read_buf, key); search_index = search_index + strlen(key) + 1 ; *search_index = value[0]; lseek(fd, 0 , SEEK_SET); write(fd, read_buf, file_size); close(fd); return 0; }
假设目录下有一个my_test.config文件
内容如下:
SPEED=5
LENG=100
SCORE=90
LEVEL=95
编译步骤:
gcc config_file.c -o config_file
./config_file my_test.config SPEED 6
结果:SPEED字段的值变为6
SPEED=6
LENG=100
SCORE=90
LEVEL=95



