😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍 read、write、lseek 函数🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
本文未经允许,不得转发!!!
目录
- 🎄一、概述
- 🎄二、read 函数
- 🎄三、write 函数
- 🎄四、lseek 函数
- ✨4.1 文件偏移量
- ✨4.2 lseek 函数
- 🎄五、总结
🎄一、概述
在Linux系统中,大多数文件I/O只需要用到5个函数:open、read、write、lseek、close,上篇文章介绍了open、creat、close,本文继续介绍剩下的读写操作相关的函数:read、write、lseek。
🎄二、read 函数
函数原型
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
read 函数可以从打开的文件描述符读取数据。
- 参数:
fd,:要操作的文件描述符
buf:目标缓冲区
count:期望读取的字节数 - 返回值:
成功:返回读取到的字节数。到达文件尾返回0。
出错:返回 -1。
返回的字节数少于要求读取的字节数的几个情况:
- 1、读取普通文件时,在读取到要求的字节数之前已经到达文件末尾。例如:距离文件尾端只有30个字节,要求读取100字节,就会返回30,下次再读取返回0.
- 2、读取终端设备时,通常一次最多读取一行;
- 3、
从网络读取数据
时,网络中的缓冲机制可能造成返回值小于要读取的字节数;- 4、当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么read将只返回实际可用的字节数。
- 5、当从某些面向记录的设备(如磁带)读时,一次最多返回一个记录。
- 6、当一信号造成中断,而已经读了部分数据量时。读操作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。
🎄三、write 函数
函数原型
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
write 函数可以向已打开的文件描述符写入数据。
- 参数:
fd:文件描述符
buf:源数据的缓冲区
count:期望写入的字节数 - 返回值:
成功:返回实际写入字节数
出错:返回 -1。
其返回值通常与参数count的值相同,否则表示出错。write出错的一个常见原因是:磁盘已写满,或者超过了一个给定进程的文件长度限制。
对于普通文件,写操作从文件的当前偏移量处开始。如果在打开该文件时,指定了O_APPEND选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写之后,该文件偏移量增加实际写的字节数。
🎄四、lseek 函数
✨4.1 文件偏移量
每个打开的文件都有一个与其相关联的“当前文件偏移量”(current file offset)。它通常是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读写的字节数。按系统默认的情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏移量被设置为0。
✨4.2 lseek 函数
函数原型
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
write 函数可以修改已打开的文件描述符的文件偏移量。
-
参数:
- fd:文件描述符
- offset:偏移量
- whence:偏移的起始位置,有三个取值
SEEK_SET
,则将该文件的偏移量设置为距文件开始处offset个字节。
SEEK_CUR
,则将该文件的偏移量设置为其当前值加offset,offset可为正或负。
SEEK_END
,则将该文件的偏移量设置为文件长度加offset,offset可为正或负。
-
返回值:
成功:移动后的目标位置与文件开始处的偏移量。
失败:返回-1。
lseek 函数执行成功后,会返回新的文件偏移量,所以用下面语句来查看文件大小和当前文件偏移量:
size = lseek(fd, 0, SEEK_END);// 文件大小
cur = lseek(fd, 0, SEEK_CUR);// 查看当前的文件偏移量
这种方法也可用来确定所涉及的文件是否可以设置偏移量。如果文件描述符引用的是一个管道、FIFO或网络套接字,则1seek返回-1,并将errno设置为ESPIPE。
通常,文件的当前偏移量应当是一个非负整数,但是,某些设备也可能允许负的偏移量。但对于普通文件,则其偏移量必须是非负值。因为偏移量可能是负值,所以,在比较lseek的返回值时应当谨慎,不要测试它是否小于0,而要测试它是否等于-1
。
lseek在超越文件末尾位置写入数据,将文件中形成空洞。文件空洞不占磁盘空间,但被算在文件大小内。
🎄五、总结
👉介绍Linux C语言编程文件I/O相关的函数:read、write、lseek。
最后看下面例子,帮助理解这几个函数:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
char buf[64] = {0};
int fd = open("./test", O_RDWR | O_CREAT | O_TRUNC, 0775);
int cur = lseek(fd, 0, SEEK_CUR);
printf("cur pos=%d\n", cur);
int writeLen = write(fd, "abcdefg", strlen("abcdefg"));
cur = lseek(fd, 0, SEEK_CUR);
printf("cur pos=%d\n", cur);
int readLen = read(fd, buf, sizeof(buf));// 文件偏移量在末端,返回0,什么也读取不到
printf("readLen=%d buf=[%s]\n", readLen, buf);
lseek(fd, -3, SEEK_CUR); // 倒退3个字节,可以读取到 efg
bzero(buf, sizeof(buf));
readLen = read(fd, buf, sizeof(buf));
printf("readLen=%d buf=[%s]\n", readLen, buf);
lseek(fd, 0, SEEK_SET); // 偏移量移到文件开头, 读取到 abcdefg
bzero(buf, sizeof(buf));
readLen = read(fd, buf, sizeof(buf));
printf("readLen=%d buf=[%s]\n", readLen, buf);
lseek(fd, 3, SEEK_END); // 在文件末尾之后再偏移 3 个字节,会形成空洞
writeLen = write(fd, "abcdefg", strlen("abcdefg")); // 写完后,会有17个字节,7+3+7
lseek(fd, 0, SEEK_SET); // 偏移量移到文件开头, 读取到 abcdefg abcdefg
bzero(buf, sizeof(buf));
readLen = read(fd, buf, sizeof(buf));
int size = lseek(fd, 0, SEEK_END); // 偏移到文件末端,查看文件大小
printf("readLen=%d buf=[%s] size=%d\n", readLen, buf, size);// 这里的buf会打印不全,因为有3个空洞字节,读出来是0
int i=0;
for(i=0; i<size; i++)
{
printf("%d=%d\n",i, buf[i]);
}
close(fd);
return 0;
}
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁