Linux下的文件操作----低级文件操作

Linux下的文件操作----低级文件操作

基于文件描述符的文件操作,无缓冲区,也称为低级文件的操作,属于底层文件系统

一、open();函数

int open(const char *pathname, int flags);

函数功能:该函数的作用是打开已存在的文件 ; 或者创建一个文件;又或者文件存在就打开,不存在就创建;具体功能由参数决定。

1、参数解释:

  1. pathname : 代表文件的路径

  2. 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); ,这样的话,如果文件不存在,则创建该文件,如果文件存在就读取该文件。

      为什么要进行 按位或运算 呢?请看下图

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UWLoTNHH-1638195411546)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20211125180538965.png)]

因为他们实质上是一个8进制数字(以0开头的是8进制),他们的每一个二进制位代表着不同的权限 。
这里我们要说一下文件的权限问题,文件的权限对于用户来说是分级的,对于每一级用户(文件属主、同组用户、其他用户),可能有不同的权限,如果你是文件的创建者(文件属主)你可能有可读、可写、可执行的的权限,同组用户和其它用户不一定有这些权限,如果不设置这个权限,系统会提供一个默认权限,这个系统默认权限,可能比你的权限还低。就拿刚才举的例子:用 open(“/home/a.txt”, O_RDWR| O_CREAT); 我的程序创建一个文件后,当我重新运行程序时,我们想当然地认为可以读取a.txt这个文件,其实在我第二次运行的时候是不能读取的! 也就是说如果我不设置我的文件的用户权限级别,我在创建该文件后,我就不能对该文件进行读写!因为我的用户权限级别,被拉低到了系统默认级别(可以理解为:因为我没设置,所以系统总要提供一个默认值,但这个默认值的权限太低了)。

在低级文件操作中只有创建文件时(O_CREAT)我们才需要设置文件的权限

那我们如何设置?

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X1KshfWn-1638195411550)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20211125195458157.png)]

​ 图1

上面说真正建文件时的权限会受到 umask 值所影响,因此该文件权限应该为(mode-umaks). 例如我给我的文件设置为如下参数:

fd=open("a.txt",O_RDWR|O_CREAT,0666);

0666 - 0002 = 0664 ,我们将得出的结果换成2进制,并结合图2—文件信息的含义、图3,来解释0664 的意义。如图4所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d7YibVvM-1638195411553)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20211125201648355.png)]

​ 图2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HyIBjo4l-1638195411556)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20211125201034685.png)]

​ 图3

在这里插入图片描述

​ 图4

umask值我们可以手动更改,例如在终端输入 umask 0000 就把值给改成了 0000

也可以在创建文件后再对文件的用户权限通过chmod进行修改

chmod 777 /home/FunctionWork/file1.c

将文件file.c 的权限提升到所有用户(可读可写可执行)

二、write();函数

ssize_t write (int fd,const void * buf,size_t count);

函数功能:是向文件里写数据

1、参数解释

  1. fd 是文件的描述符,是open() 函数的返回值
  2. buf 是将buf里的内容写入到fd 所指的文件里,写入count个字节。 解释:void* 类型的指针什么意思?你可以把它理解为万能指针,即什么类型的指针都能接受,传什么指针就是什么指针。
  3. count 一次写入到文件里的字节数

2、返回值

返回写入文件的字节数

ssize_t 其实是 long类型,只不过开发人员为了提高可读性用typedef 把long 重命名为了 ssize_t

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ksMlRnRD-1638195639458)(C:\Users\纵横四海\AppData\Roaming\Typora\typora-user-images\image-20211129192411908.png)]

三、lseek();函数

off_t lseek(int fildes,off_t offset,int whence);

函数功能:我们打开一个文件无非是对文件进行读或者写,这就需要一个读写位置,一般情况下是从文件的开头开始读写,但如果是追加模式的话(O_APPEND),读写位置会指向文件末尾。如果我们想自己指定位置进行文件的读写操作,就可以用lseek();函数。

1、参数解释

  1. fildes 是文件标识符

  2. offset 读写位置的偏移量,根据whence来确定偏移方式

  3. 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、参数解释

  1. fd 文件标识符
  2. buf 接受数据的指针,即将读取的数据存到buf所指向的地址空间,关于void* 什么意思在上面write函数部分已经提到过
  3. 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;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值