Linux C应用编程1—文件IO基础篇,open、read、close、lseek函数讲解
0.参考资料
视频参考:正点原子嵌入式LinuxC应用编程视频教程,b站搜索正点原子官方即可观看
https://space.bilibili.com/394620890?spm_id_from=333.337.0.0
文档参考:正点原子的I.MX6ULL嵌入式Linux C应用编程指南,搜索引擎搜索正点原子资料下载中心可获取
http://47.111.11.73/docs/boards/arm-linux/index.html
1.文件IO释义
通俗来说,文件IO就是指对文件的读写操作
基本流程:
打开文件——读写文件——关闭文件
2.文件描述符
文件描述符是一个非负的整型数值,其“身份”其实是文件句柄。
在定义时会写成如下形式:
int fd;
int fd1,fd2;
当使用者使用open()时,会分配一个没有使用过的最小非负整数作为句柄,这个最小非负整数与要打开的文件是绑定在一起的。
标准输入、标准输出和标准错误的0,1,2是从父进程中继承的。
3.open()函数
open()作用:1.打开文件 2.创建文件
函数原型:
int open(const char *pathname, int flags):
int open(const char *pathname, int flags, mode_t mode);
open()是可变参的,当需要创建文件的时候使用3个参数的open()。
参数:
pathname:打开文件的路径。
flags:标志(规定文件特性)。
mode:设置文件权限(创建时)。
返回值:
执行成功会发挥一个非负整数值,失败返回-1。
对于flags参数,有以下一些常用的标志,参考自正点原子I.MX6U嵌入式Linux C应用编程指南:
如果还想继续了解open函数的使用,可以在终端命令行输入下方命令进行查询:
man 2 open
对于mode参数,代表的是创建文件的权限,一个文件的权限分为3种:可执行、可读、可写。mode是32位的无符号整型数据(u32),且我们是通过改变这个数的低12位来控制权限的。
图片摘自正点原子I.MX6U嵌入式Linux C应用编程指南
重点需要介绍的是UGO这三个位置,因为S表示的是文件的特殊权限,使用的较少。
U:文件所属用户权限
G:同组用户(Group)权限,即与文件所有者有同组ID的所有用户
O:其他用户的权限
我们可以看到UGO这三部分的每一个部分上都有3位,3位数字分别代表的是rwx,即读、写、可执行权限。
最高权限表示方法: 111111111 (二进制表示) 、777 (八进制表示) 、511 (十进制表示)。一般习惯用8进制进行表示。
4.write()函数
函数原型:
ssize_t write(int fd, const void *buf, size_t count);
参数:
fd:目标文件,必须保证使用前已经open了该文件
buf:存放要写入文件的数据
count:要写入的字节数
返回值:
成功写入的字节数,写入错误返回-1
读写位置:
有专门的读写指针指向读写的位置,读写的指针是共用的,open之后默认读写指针指向第0位,如果需要重新设置读写指针位置可以使用lseek()函数。
5.read()函数
函数原型:
ssize_t read(int fd, void *buf, size_t count):
参数:
fd:目标文件
buf:存放读取到的数据
count:指定读取的字节数
返回值:
成功读取返回读取到的字节数,错误则返回-1。
6.close()函数
函数原型:
int close(int fd);
参数:
fd:目标文件
返回值:
关闭成功则返回0,失败则返回-1。
7.lseek()函数
调整文件读写位置偏移。
函数原型:
off_t lseek(int fd, off_t offset, int whence):
参数:
fd:文件描述符。
offset:偏移量,以字节为单位。
whence:用于定义参数 offset 偏移量对应的参考值。指定读写偏移量起始位置。
whence定义有一些宏,可以直接使用:
SEEK_SET:读写偏移量将指向 ofset 字节位置处(从文件头部开始算) 。
SEEK_CUR:读写偏移量将指向当前位置偏移量 +offset 字节位置处,offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移。
SEEK_END:读写偏移量将指向文件末尾 +offset 字节位置处,同样 offset 可以为正、也可以为负,如果是正数表示往后偏移、如果是负数则表示往前偏移。
返回值:
成功执行返回从文件头部算起的位置偏移量即当前读写位置(单位:字节),发生错误则返回-1。
8.例程
这里我使用的是vim编辑器,通过gcc进行编译。没有安装的需要先安装。
例程1:open,write,close函数使用
//新建一个文件test1.txt,写入“Hello World”,对新建文件的要求O、G用户对文件只有可读权限,U用户对文件具有可读可写权限
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
int fd;
int ret;
fd = open("./test1.txt",O_WRONLY|O_CREAT|O_EXCL,0644);
if(-1 == fd)
{
printf("open error!\n");
return -1;
}
printf("open sucess!\n");
ret = write(fd,"Hello World",11);
if(-1 == ret)
{
printf("write error!");
close(fd);
return -1;
}
printf("write %d bytes sucess!\n",ret);
close(fd);
return 0;
}
运行结果:
可以发现,test1.txt成功建立,打开文件可以发现Hello World已经成功写入test1.txt。
例程2:open、read、close函数的使用
//读取文件test1.c里面的内容
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
int fd;
char buf[128] = {0};
int ret;
fd = open("./test1.txt",O_RDONLY);
if(-1 == fd)
{
printf("open error!\n");
return -1;
}
printf("open sucess!\n");
ret = read(fd,buf,11);
if(-1 == ret)
{
printf("read error!\n");
close(fd);
return -1;
}
printf("read %d bytes: %s\n",ret,buf);
close(fd);
return 0;
}
运行结果:
例程3:lseek的使用
//计算某个文件的大小
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc,char *argv[])
{
int fd;
int len;
fd = open("./text.txt",O_RDONLY);
if(-1 == fd)
{
printf("open error!\n");
return -1;
}
len = lseek(fd,0,SEEK_END);
if(-1 == len)
{
printf("lseek error!");
return -1;
}
printf("the length of file: %d\n",len);
close(fd);
return 0;
}
运行结果: