Linux标准IO 文本IO lseek fseek

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

上期发布了标准IO和文本IO,接下来是文本IO的lseek的详细解析


提示:以下是本篇文章正文内容,下面案例可供参考

一、文本IO lseek

lseek 读写偏移量 用于指示 read()或 write()函数操作时文件的起始位置,会以相对于文件头部的位置偏移量来表示,文件第一个字节数据的位置偏移量为 0。
当打开文件时,会将读写偏移量设置为指向文件开始位置处,以后每次调用 read()、write()将自动对其进行调整,以指向已读或已写数据后的下一字节,因此,连续的调用 read()和 write()函数将使得读写按顺序递增,对文件进行操作。我们先来看看 lseek 函数的原型,如下所示(可通过"man 2 lseek"查看):
#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
首先调用 lseek 函数需要包含<sys/types.h>和<unistd.h>两个头文件。
函数参数和返回值含义如下:
**fd:**文件描述符。
**offset:**偏移量,以字节为单位。
**whence:**用于定义参数 offset 偏移量对应的参考值,该参数为下列其中一种(宏定义):
SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算);
SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处,offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移;
SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处,同样 offset 可以为正、也可以为负,如果是正数表示往后偏移、如果是负数则表示往前偏移。
返回值:成功将返回从文件头部开始算起的位置偏移量(字节为单位),也就是当前的读写位置;发生错误将返回-1。
使用示例:
将读写位置移动到文件开头处:
off_t off = lseek(fd, 0, SEEK_SET);
if (-1 == off)
return -1;
将读写位置移动到文件末尾:
off_t off = lseek(fd, 0, SEEK_END);

if (-1 == off)
return -1;
将读写位置移动到偏移文件开头 100 个字节处:
off_t off = lseek(fd, 100, SEEK_SET);

if (-1 == off)
return -1;
获取当前读写位置偏移量:
off_t off = lseek(fd, 0, SEEK_CUR);
if (-1 == off)
return -1;
函数执行成功将返回文件当前读写位置

二、标准IO fseek

库函数 fseek()的作用类似于所学习的系统调用 lseek(),用于设置文件读写位置偏移量,lseek()用于文件 I/O,而库函数 fseek()则用于标准 I/O,其函数原型如下所示:
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
函数参数和返回值含义如下:
stream:FILE 指针。
offset:与 lseek()函数的 offset 参数意义相同。
whence:与 lseek()函数的 whence 参数意义相同。
返回值:成功返回 0;发生错误将返回-1,并且会设置 errno 以指示错误原因;与 lseek()函数的返回值意义不同,这里要注意!
调用库函数 fread()、fwrite()读写文件时,文件的读写位置偏移量会自动递增,使用 fseek()可手动设置文件当前的读写位置偏移量。
2. 0、1、2 这三个是文件描述符,只能用于文件 I/O(read()、write()等),那么在标准 I/O 中,自然是无法使用文件描述符来对文件进行 I/O 操作的,它们需要围绕 FILE 类型指针来进行,在 stdio.h 头文件中有相应的定义,struct _IO_FILE 结构体就是 FILE 结构体,使用了 typedef 进行了重命名。所以,在标准 I/O 中,可以使用 stdin、stdout、stderr 来表示标准输入、标准输出和标准错误。
3. 文件描述符与 FILE 指针互转
4.10 文件描述符与 FILE 指针互转
在应用程序中,在同一个文件上执行 I/O 操作时,还可以将文件 I/O(系统调用 I/O)与标准 I/O 混合使用,这个时候我们就需要将文件描述符和 FILE 指针对象之间进行转换,此时可以借助于库函数 fdopen()、fileno()来完成。

三、拓展

库函数 fileno()可以将标准 I/O 中使用的 FILE 指针转换为文件 I/O 中所使用的文件描述符,而 fdopen()则进行着相反的操作,其函数原型如下所示:
#include <stdio.h>
int fileno(FILE *stream);
FILE *fdopen(int fd, const char *mode);
首先使用这两个函数需要包含头文件<stdio.h>。对于 fileno()函数来说,根据传入的 FILE 指针得到整数文件描述符,通过返回值得到文件描述符,如果转换错误将返回-1,并且会设置 errno 来指示错误原因。得到文件描述符之后,便可以使用诸如 read()、write()、lseek()、fcntl()等文件 I/O 方式操作文件。
fdopen()函数与 fileno()功能相反,给定一个文件描述符,得到该文件对应的 FILE 指针,之后便可以使用诸如 fread()、fwrite()等标准 I/O 方式操作文件了。参数 mode 与 fopen()函数中的 mode 参数含义相同,具体参考表 4.4.1 中所述,若该参数与文件描述符 fd 的访问模式不一致,则会导致调用 fdopen()失败。
当混合使用文件 I/O 和标准 I/O 时,需要特别注意缓冲的问题,文件 I/O 会直接将数据写入到内核缓冲区进行高速缓存,而标准 I/O 则会将数据写入到 stdio 缓冲区,之后再调用 write()将 stdio 缓冲区中的数据写入到内核缓冲区。譬如下面这段代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf(“print”);
write(STDOUT_FILENO, “write\n”, 6);
exit(0);
}
执行结果你会发现,先输出了"write"字符串信息,接着再输出了"print"字符串信息,产生这个问题的原因很简单,大家自己去思考下!


总结

后续相关内容持续更新!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芯片烧毁大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值