Linux下的文件操作----低级文件操作
基于文件描述符的文件操作,无缓冲区,也称为低级文件的操作,属于底层文件系统
一、open();函数
int open(const char *pathname, int flags);
函数功能:该函数的作用是打开已存在的文件 ; 或者创建一个文件;又或者文件存在就打开,不存在就创建;具体功能由参数决定。
1、参数解释:
-
pathname : 代表文件的路径 -
flags:文件状态控制符,它的作用是:
-
规定文件的读写权限 O_RDONLY (仅可读) O_WRONLY(仅可写), O_RDWR(可读可写),而且只能包含三者中的一个 -
创建文件,当这个文件不存在时你可以通过O_CREAT创建文件 -
除了上面提到的它还有很多可用参数如: O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOLLOW, O_TMPFILE, O_TRUNC等等,我们可以对他们进行组合使用,例如: ? 当我们不知道一个文件存不存在,还需要可读可写的权限时,我们可以这样配置:open(“/home/a.txt”, O_RDWR| O_CREAT); ,这样的话,如果文件不存在,则创建该文件,如果文件存在就读取该文件。 为什么要进行 按位或运算 呢?请看下图
因为他们实质上是一个16进制数字,他们的每一个二进制位代表着不同的权限 。
这里我们要说一下文件的权限问题,文件的权限对于用户来说是分级的,对于每一级用户(文件属主、同组用户、其他用户),可能有不同的权限,如果你是文件的创建者(文件属主)你可能有可读、可写、可执行的的权限,同组用户和其它用户不一定有这些权限,如果不设置这个权限,系统会提供一个默认权限,这个系统默认权限,可能比你的权限还低。就拿刚才举的例子:用 open(“/home/a.txt”, O_RDWR| O_CREAT); 我的程序创建一个文件后,当我重新运行程序时,我们想当然地认为可以读取a.txt这个文件,其实在我第二次运行的时候是不能读取的! 也就是说如果我不设置我的文件的用户权限级别,我在创建该文件后,我就不能对该文件进行读写!因为我的用户权限级别,被拉低到了系统默认级别(可以理解为:因为我没设置,所以系统总要提供一个默认值,但这个默认值的权限太低了)。
那我们如何设置?
int open(const char *pathname, int flags); 该函数没有对应参数,但是 int open(const char *pathname, int flags, mode_t mode); 有相应参数,下面会讲。
2、返回值
open函数的返回值如果操作成功,它将返回一个文件描述符,可通过这个描述符对文件进行读写,如果操作失败,它将返回-1。
int open(const char *pathname, int flags, mode_t mode);
这里仅讲解mode参数的作用 ,mode参数就是来设置用户权限的,真正建文件时的权限会受到 umask 值所影响,因此 该文件权限应该为(mode-umaks).
什么是umask值呢?这里引用他人的解释
源引地址1: https://zhidao.baidu.com/question/143402104.html
我们创建文件的默认权限是怎么来的?如何改变这个默认权限呢? umask是什么? 当我们登录系统之后创建一个文件总是有一个默认权限的,那么这个权限是怎么来的呢?这就是umask干的事情。umask设置了用户创建文件的默认权限,它与chmod的效果刚好相反,umask设置的是权限“补码”,而chmod设置的是文件权限码。一般在/etc/profile、$ [HOME]/.bash_profile或$[HOME]/.profile中设置umask值。 如何计算umask值? umask命令允许你设定文件创建时的缺省模式,对应每一类用户(文件属主、同组用户、其他用户)存在一个相应的umask值中的数字。对于文件来说,这一数字的最大值分别是6。系统不允许你在创建一个文本文件时就赋予它执行权限,必须在创建后用chmod命令增加这一权限。目录则允许设置执行权限,这样针对目录来说,umask中各个数字最大可以到7。 该命令的一般形式为:umask nnn 其中nnn为umask置000 - 777。 我们只要记住umask是从权限中“拿走”相应的位即可。 如:umask值为022,则默认目录权限为755,默认文件权限为644。
源引地址2:https://blog.csdn.net/weixin_30395665/article/details/116652907
umask值用于设置用户在创建文件时的默认权限,当我们在系统中创建目录或文件时,目录或文件所具有的默认权限就是由umask值决定的。
对于root用户,系统默认的umask值是0022;对于普通用户,系统默认的umask值是0002。执行umask命令可以查看当前用户的umask值。
? 下图是我当前用户的 umask值 是 0002
? 图1
上面说真正建文件时的权限会受到 umask 值所影响,因此该文件权限应该为(mode-umaks). 例如我给我的文件设置为如下参数:
fd=open("a.txt",O_RDWR|O_CREAT,0666);
0666 - 0002 = 0664 ,我们将得出的结果换成2进制,并结合图2—文件信息的含义、图3,来解释0664 的意义。如图4所示:
? 图2
? 图3
? 图4
也可以在创建文件后再对文件的用户权限通过chmod进行修改
chmod 777 /home/FunctionWork/file1.c
将文件file.c 的权限提升到所有用户(可读可写可执行)
二、write();函数
ssize_t write (int fd,const void * buf,size_t count);
函数功能:是向文件里写数据
1、参数解释
- fd 是文件的描述符,是open() 函数的返回值
- buf 是将buf里的内容写入到fd 所指的文件里,写入count个字节。 解释:void* 类型的指针什么意思?你可以把它理解为万能指针,即什么类型的指针都能接受,传什么指针就是什么指针。
- count 一次写入到文件里的字节数
2、返回值
返回写入文件的字节数
ssize_t 其实是 long类型,只不过开发人员为了提高可读性用typedef 把long 重命名为了 ssize_t
三、lseek();函数
off_t lseek(int fildes,off_t offset,int whence);
函数功能:我们打开一个文件无非是对文件进行读或者写,这就需要一个读写位置,一般情况下是从文件的开头开始读写,但如果是追加模式的话(O_APPEND),读写位置会指向文件末尾。如果我们想自己指定位置进行文件的读写操作,就可以用lseek();函数。
1、参数解释
-
fildes 是文件标识符 -
offset 读写位置的偏移量,根据whence来确定偏移方式 -
whence 设定偏移方式的参数,有以下三个参数可供选择: ? SEEK_SET 参数 offset 即为新的读写位置。 ? SEEK_CUR 以目前的读写位置往后增加 offset 个位移量。 ? SEEK_END 将读写位置指向文件尾后再增加 offset 个位移量 例如: ? 设置读写位置在文件开头:lseek ( int fildes , 0 , SEEK_SET ); ? 将读写位置移到文件末尾:lseek ( int fildes,0,SEEK_END ); ? 获取前读写位置:lseek ( int fildes,0,SEEK_CUR );
值得注意的是:当偏移方式选择SEEK_CUR 时,如果我们进行写之后再进行读,此时读的位置是接续写的位置继续往后偏移的,先读再写也是一样的。可以通过关闭文件再重新打开文件来解决。
2、返回值
当调用成功时则返回目前的读写位置,也就是距离文件开头多少个 字节。若有错误则返回 -1 .
四、read();函数
ssize_t read(int fd,void * buf ,size_t count);
函数功能:从文件里读取数据
1、参数解释
- fd 文件标识符
- buf 接受数据的指针,即将读取的数据存到buf所指向的地址空间,关于void* 什么意思在上面write函数部分已经提到过
- count 从文件中一次读取count个字节
2、返回值
返回读取了多少个字节
代码示例
将数据写入文件再读出来,具体代码如下:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
int main(int argc,char *argv[])
{
int fd=-1;
char buf[100]={0};
char writebuf[20]="you are beautiful!";
int ret=-1;
fd=open("a.txt",O_RDWR|O_CREAT,0666);
if(-1==fd)
{
printf("open error");
}
else
{
printf("open sucess,fd=%d.\n",fd);
}
ret=lseek(fd,0,SEEK_SET);
ret=write(fd,writebuf,sizeof(writebuf));
if(ret<0)
{
printf("write error\n");
}
else
{
printf("write sucess,write %d char .\n",ret);
}
ret=lseek(fd,0,SEEK_SET);
ret=read(fd,buf,sizeof(writebuf));
if(ret<0)
{
printf("read error\n");
}
else
{
printf("read %d byte .\n",ret);
printf("the content are:[%s].\n",buf);
}
close(fd);
return 0;
}
|