wx:嵌入式工程师成长日记
https://mp.weixin.qq.com/s/NbYVE8hsU7V_48nbNsUByA?token=382885458&lang=zh_CNhttps://mp.weixin.qq.com/s/NbYVE8hsU7V_48nbNsUByA?token=382885458&lang=zh_CN
操作文件有专属的系统函数,系统函数并不是内核函数,因为内核函数是不允许用户使用的,系统函数就充当了二者之间的桥梁,这样用户就可以间接的完成某些内核操作了。
在Linux系统中必须要使用系统提供的IO函数才能基于这些文件描述符完成对相关文件的读写操作。
1.open()
open()是一个系统函数,只能在linux系统中使用, windows不支持。
fopen() 是标准c库函数, 一般可以跨平台使用。
// 打开一个已经存在的磁盘文件
int open(const char *pathname, int flags);
// 打开磁盘文件, 如果文件不存在, 就会自动创建
int open(const char *pathname, int flags, mode_t mode);
参数:
1.pathname: 被打开的文件的路径文件名
2.flags:使用什么方式打开指定的文件,必须要指定的属性, 以下三个属性不能同时使用, 只能任选其一:
O_RDONLY: 以只读方式打开文件
O_WRONLY: 以只写方式打开文件
O_RDWR: 以读写方式打开文件
(可选属性):
O_APPEND: 新数据追加到文件尾部, 不会覆盖文件的原来内容
O_CREAT: 如果文件不存在, 创建该文件, 如果文件存在什么也不做
O_EXCL: 检测文件是否存在, 必须要和O_CREAT 一起使用, 不能单独使用: O_CREAT | O_EXCL;(若检测到文件不存在, 则创建新文件,检测到文件已经存在,创建失败,函数直接返回-1)
3.mode: 在创建新文件的时候才需要指定这个参数的值,用于指定新文件的权限,这是一个八进制的整数。(该最大值为:0777)
创建的新文件对应的最终实际权限, 计算公式: (mode & ~umask)
umask 掩码可以通过 umask 命令查看
4.返回值:
成功: 返回内核分配的文件描述符,是一个大于0的整数
失败: -1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main()
{
// 打开文件
int fd = open("abc.txt", O_RDWR);
if(fd == -1)
{
printf("打开文件失败\n");
}
else
{
printf("fd: %d\n", fd);
}
close(fd);
return 0;
}
2.close()
功能:关闭文件并释放文件描述符
#include <unistd.h>
int close(int fd);
3.read()
功能:用于读取文件内部数据
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
参数:
fd: 文件描述符, open() 函数的返回值,通过这个参数定位打开的磁盘文件
buf: 传出参数, 指向一块有效的内存, 用于存储从文件中读出的数据
count: buf指针指向的内存的大小, 指定可以存储的最大字节数
返回值:
大于0: 从文件中读出的字节数,读文件成功
等于0: 代表文件读完了,读文件成功
-1: 读文件失败
4.write()
功能:用于将数据写入到文件内部
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数:
fd: 文件描述符, open() 函数的返回值, 通过这个参数定位打开的磁盘文件
buf: 指向一块有效的内存地址, 里边有要写入到磁盘文件中的数据
count: 要往磁盘文件中写入的字节数, 一般情况下就是buf字符串的长度, 调用strlen(buf)即可求得
返回值:
大于0: 成功写入到磁盘文件中的字节数
-1: 写文件失败了
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main()
{
// 打开存在的文件a.txt, 读这个文件
int fd1 = open("./a.txt", O_RDONLY);
if(fd1 == -1)
{
perror("error");
return -1;
}
// 打开不存在的文件, 将其创建出来, 将从a.txt读出的内容写入这个文件中
int fd2 = open("b.txt", O_WRONLY|O_CREAT, 0664);
if(fd2 == -1)
{
perror("error");
return -1;
}
// 循环读文件, 循环写文件
char buf[4096];
int len = -1;
while( (len = read(fd1, buf, sizeof(buf))) > 0 )
{
// 将读到的数据写入到另一个文件中
write(fd2, buf, len);
}
// 关闭文件
close(fd1);
close(fd2);
return 0;
}
5.lseek()
功能:通过这个函数移动文件指针, 也可以通过这个函数进行文件的拓展
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数:
fd: 文件描述符, open() 函数的返回值, 通过这个参数定位打开的磁盘文件
offset: 偏移量,需配合第三个参数使用
whence: 以下三个参数任选其中一个
SEEK_SET: 从文件头部开始偏移 offset 个字节
SEEK_CUR: 从当前文件指针的位置向后偏移offset个字节
SEEK_END: 从文件尾部向后偏移offset个字节
返回值:
成功: 文件指针从头部开始计算总的偏移量
失败: -1
三种用法:
//文件指针移动到文件头部
lseek(fd, 0, SEEK_SET);
//得到当前文件指针的位置
lseek(fd, 0, SEEK_CUR);
//得到文件总大小
lseek(fd, 0, SEEK_END);
利用lseek()实现文件扩展
注意:
使用 lseek 函数进行文件拓展必须要满足以下条件:
1.文件指针必须要偏移到文件尾部之后,多出来的就需要被填充的部分
2.文件拓展之后,必须要使用write()函数进行一次写操作(写什么都可以)
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd = open("a.txt", O_RDWR);
if(fd == -1)
{
perror("error");
return -1;
}
// 文件一共拓展了 1001 个字节
lseek(fd, 1000, SEEK_END);
write(fd, " ", 1);
close(fd);
return 0;
}
6.truncate()/ftruncate()
功能:修改指定文件大小,用来拓展文件,比lseek()使用更简单
#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path, off_t length);-
int ftruncate(int fd, off_t length);
参数:
path: 要拓展/截断的文件的文件名
fd: 文件描述符
length: 有以下两种情况:
①文件原来size > length,文件被截断, 尾部多余的部分被删除, 文件最终长度为length
②文件原来size < length,文件被拓展, 文件最终长度为length
返回值:
成功则返回0
失败则返回-1