linux、c文件IO(open,read,write,lseek,close)

linux、c文件IO(open,read,write,lseek,close)

​ 注意区分文件IO和标准IO,文件IO是内核中的系统调用,而标准IO为标准库种封装好的函数接口。

0.文件描述符

​ 学习文件IO或者标准IO需要先掌握文件描述符的概念,在UNIX系统种,一切皆文件,对于每个打开的(注意是打开的)文件都有一个对应的非负整数作为其文件描述符,其中标准输入(可理解为你在终端中输入的内容),标准输出(可理解为往终端上输出),标准错误(用来输出错误信息)分别对应0, 1, 2的默认文件描述符。所以再有其他打开的文件时,描述符会从未被使用的最小整数开始(从3开始)。

1.open
//用法,第三个参数写为“...”,只在文件不存在需要用open创建时使用:1.文件路径与文件名 2.用来设定对文件操作权限的标志位 3.所创建文件的权限信息
//打开成功返回对应的文件描述符, 出错返回-1
int open(const char *path, int oflag, ...mode);

常见的标志位(参数2):

​ (Tip:对于此种大写的变量名,应该很容易联想到这只是一些数字的宏定义而已)

O_RDONLY:只读方式打开文件。
O_WRONLY:可写方式打开文件。
O_RDWR: 读写方式打开文件。
以上这三个参数互斥
O_CREAT:如果该文件不存在,就创建一个新的文件,并用第三个参数为其设置权限。
O_TRUNC:如文件已经存在,那么打开文件时将文件长度截取为0(即达到清空文件的目的)
O_APPEND:以添加方式打开文件,所有对文件的写操作都在文件的末尾进行(可理解为打开文件时将光标放在末尾)。

*此外,也可用creat函数创建新文件

2.close

​ 用于关闭文件描述符所对应的文件

//成功返回0, 出错返回-1
int close(int fd);

​ 尽量在对文件操作完后进行关闭,当然如果忘记写此函数,当程序结束时(即你写的代码关闭时),内核会自动关闭该程序所有的以打开文件。

3.lseek

​ 每个文件都有一个“当前文件偏移量”(说白了就例如你写文档时的“光标”位置到文件开始处(0位置)之间的字节数的值),通过lseek可以指定和移动“光标”的位置。

//off_t是文件偏移量类型,实际上就是个长整型(long int(32位)或long long int(64位))
//三个参数:1。文件描述符 2.偏移量,根据参数3不同有不同的含义 3.见下面的详细解释
//成功返回新的当前的文件偏移量, 出错返回-1
off_t lseek(int fd, off_t offset, int whence);

参数三:

SEEK_SET,将文件偏移量设置为 距离文件开始处offset(参数2)个字节(绝对偏移量)

SEEK_CUR,将文件偏移量设置为 当前偏移量 加上 offset,所以offset可为负数(相对当前位置偏移量)

SEEK_END,将文件偏移量设置为 文件长度 (即光标在文件末尾)加 offset,可为负数。(相对末尾偏移量)

​ (很多地方直接用0、1、2代替上面这三个也是可以的)

4.read

​ 用于从打开文件读取数据

//size_t为无符号整型,而ssize_t为有符号整型(因为错误时需要返回-1)
//参数:1.已打开文件的文件描述符 2.通常是char *,是从fd文件中读取到数据的存放地址 3.读取的大小
//成功返回 读取到的字节数, 出错返回-1
ssize_t read(int fd, void *buf, size_t nbytes);

一些点:

  • 若 读取字节 < nbytes 时已到达文件末尾,则返回实际读取的字节大小

  • 还记得标准输入也是有文件描述符的吗,所以可用read来读取终端中输入的命令内容,通常一次最多读一行

5.write

​ 向打开的文件中写数据

//三个参数,1.文件描述符 2.要往文件中写入的数据的地址 3.要求写入的字节数
//成功返回已写入的字节数(通常与nbytes相等), 出错返回-1
ssize_t write(int fd, const void * buf, size_t nbytes);

​ write出错的原因一般就是 磁盘已满 或者 说数据长度超过了该进程的文件长度限制

6.其他

​ 文件IO最常用的为上面5个,与这几个相关的还有 openat,pread, pwrite等针对某些特定情况的优化版,说明一些pread和pwrite的用途。

  • ssize_t pread(int fd, void * buf, size_t nybtes, off_t offset);
    
  • ssize_t pwrite(int fd, const void * buf, size_t nbytes, off_t offset); 
    

​ 可以看到,pread或者pwrite对于原本的read,write函数多了一个 文件偏移量 的参数,对于原本的read、write函数对文件操作时,一般需要依赖于open、lseek等函数,比如说本来的目的是 打开文件后写入数据,但是由于在你 open 与 write 之间是不连贯的,如果有其他程序在你open后但还未write前对文件进行操作, 那么你的write就会出现问题。 而pread与pwrite的出现就是为了让这例如open与write这两个操作连贯起来(变为一个,即原子操作),增加安全性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值