当前位置: 首页 > news >正文

深入解析Linux下的`lseek`函数:文件定位与操作的艺术

深入解析Linux下的`lseek`函数:文件定位与操作的艺术

  • 1. `lseek`函数的功能与参数
    • 参数说明:
    • 返回值:
    • 错误处理:
  • 2. 写完文件再读
    • 示例代码:
    • 注意事项:
  • 3. 使用`lseek`读取文件大小
    • 示例代码:
    • 注意事项:
  • 4. 使用`lseek`扩展文件大小
    • 示例代码:
    • 注意事项:
  • 5. 与标准库`fseek`函数的比较
    • 示例代码:
    • 注意事项:
  • 总结

在Linux系统编程中,lseek函数是一个不可或缺的工具,它允许开发者精确控制文件指针的位置,从而实现高效的文件读取、写入和扩展操作。本文将深入探讨lseek函数的各个方面,包括其功能、使用场景、实际应用案例以及与其他类似函数的比较,帮助开发者全面掌握这一重要工具。


1. lseek函数的功能与参数

lseek函数用于改变与文件描述符关联的文件指针的位置。其函数原型如下:

#include <sys/types.h>
#include <unistd.h>off_t lseek(int fd, off_t offset, int whence);

参数说明:

  • fd :文件描述符,必须有效且已打开。
  • offset :偏移量,表示从whence指定的起始点开始移动的距离。
  • whence :指定起始点,取值为:
    • SEEK_SET:文件开头。
    • SEEK_CUR:当前文件指针位置。
    • SEEK_END:文件末尾。

返回值:

  • 成功时,返回新的文件指针位置(以字节为单位)。
  • 失败时,返回-1,并设置errno

错误处理:

  • EBADF:文件描述符无效。
  • EINVALwhence参数无效。
  • ESPIPE:尝试对管道、套接字或类似设备进行写入操作。

2. 写完文件再读

在Linux中,写完文件后,文件指针位于文件末尾。如果需要读取文件内容,必须先调整文件指针的位置。

示例代码:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 写入数据char* data = "Hello, World!";write(fd, data, strlen(data));// 写完后,文件指针在末尾,无法直接读取// 需要调整文件指针到开头if (lseek(fd, 0, SEEK_SET) == -1) {perror("lseek");close(fd);exit(EXIT_FAILURE);}// 以读模式打开文件(注意:必须重新打开文件,因为写模式下无法读取)close(fd);fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 读取数据char buffer[1024];int bytes_read = read(fd, buffer, sizeof(buffer)-1);if (bytes_read == -1) {perror("read");close(fd);exit(EXIT_FAILURE);}buffer[bytes_read] = '\0';printf("Read: %s\n", buffer);close(fd);return 0;
}

注意事项:

  • 写入文件后,文件描述符处于写模式,无法直接读取。需要重新以读模式打开文件。
  • 使用lseek调整文件指针位置时,必须确保文件描述符有效。

3. 使用lseek读取文件大小

lseek可以用来获取文件的大小。通过将文件指针移动到文件末尾,可以得到文件的总字节数。

示例代码:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {int fd = open("test.txt", O_RDONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 移动文件指针到文件末尾off_t file_size = lseek(fd, 0, SEEK_END);if (file_size == -1) {perror("lseek");close(fd);exit(EXIT_FAILURE);}printf("File size: %ld bytes\n", file_size);close(fd);return 0;
}

注意事项:

  • 文件必须以读模式打开,否则可能导致错误。
  • lseek返回的是文件指针的新位置,即文件的总大小。

4. 使用lseek扩展文件大小

可以通过lseek将文件指针移动到所需位置,然后写入数据来扩展文件大小。

示例代码:

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 写入初始数据char* data = "Hello, World!";write(fd, data, strlen(data));// 移动文件指针到新的位置(扩展文件)off_t new_size = 1024; // 扩展到1024字节if (lseek(fd, new_size - 1, SEEK_SET) == -1) {perror("lseek");close(fd);exit(EXIT_FAILURE);}// 写入一个字节来扩展文件char zero = '\0';write(fd, &zero, 1);close(fd);return 0;
}

注意事项:

  • 移动文件指针到new_size - 1,然后写入一个字节,以确保文件大小扩展到new_size
  • 文件必须以写模式打开,否则可能导致错误。

5. 与标准库fseek函数的比较

fseek是C标准库函数,用于调整文件指针的位置。以下是lseekfseek的比较:

属性lseekfseek
参数int fdFILE *stream
返回值off_tint
文件描述符使用文件描述符使用FILE指针
处理方式系统调用库函数
错误处理设置errno返回非零值表示错误

示例代码:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>int main() {int fd = open("test.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}// 使用`lseek`if (lseek(fd, 10, SEEK_SET) == -1) {perror("lseek");close(fd);exit(EXIT_FAILURE);}// 使用`fseek`FILE *fp = fdopen(fd, "r+");if (fseek(fp, 10, SEEK_SET) != 0) {perror("fseek");fclose(fp);exit(EXIT_FAILURE);}fclose(fp);close(fd);return 0;
}

注意事项:

  • lseek是系统调用,性能更高,但需要处理文件描述符。
  • fseek是库函数,使用更方便,但性能稍低。

总结

lseek函数在Linux系统编程中是一个非常有用的工具,能够帮助开发者精确控制文件指针的位置。通过本文的介绍,读者可以更好地理解lseek的用法及其在实际开发中的应用。希望本文对您有所帮助!

http://www.dtcms.com/a/486718.html

相关文章:

  • Linux C/C++ 学习日记(25):KCP协议:普通模式与极速模式
  • 网站结构 网站内容建设现在建个企业网站要多少钱
  • C++ I/O流的全新边界
  • MySQL————内置函数
  • 精通iptables:从基础到实战安全配置
  • OpenAI发布构建AI智能体的实践指南:实用框架、设计模式与最佳实践解析
  • 如何使用网站模板金华关键词优化平台
  • php大气企业网站东莞邦邻网站建设
  • 简述php网站开发流程网站 设计公司 温州
  • thinkphp8+layui多图上传,带删除\排序功能
  • LeetCode 合并K个升序链表
  • FFmpeg 基本API avformat_alloc_context 函数内部调用流程分析
  • ubuntu系统中ffmpeg+x264简易编译安装指南
  • FLAC to MP3 批量转换 Python
  • 开源鸿蒙6.1和8.1版本被确定为LTS建议版本,最新路标正式发布!-转自开源鸿蒙OpenHarmony社区
  • linux sdl图形编程之helloworld.
  • 开发一个网站系统报价电子商务网站建设试卷及答案
  • 瑞芯微算法环境搭建(2)------编译opencv
  • 计算机视觉(opencv)——人脸网格关键点检测
  • 自己做网站投入编程培训机构需要哪些证件
  • AXI总线的基础知识
  • 【泛微OA】泛微OA平台实现计算具体的天数
  • 「深度学习笔记1」深度学习全面解析:从基本概念到未来趋势
  • puppeteer 生成pdf,含动态目录,目录带页码
  • 深度学习的卷积神经网络中医舌诊断病系统-ResNet50与VGG16方法的比较研究
  • 如何查看网站空间wordpress图片多选
  • Android的Activity与intent知识点
  • 一、前置基础(MVC学习前提)_核心特性_【C# MVC 前置】委托与事件:从 “小区通知” 看懂 MVC 过滤器的底层逻辑
  • 网站建设年度汇报详情页设计理念怎么写
  • Spring Boot项目中Maven引入依赖常见报错问题解决