linux文件I/O之 close()、lseek()、read()、write() 函数用法

news2024/10/7 8:23:53

 1. close() 函数

头文件和函数声明

#include <unistd.h>

int close(int fd);

函数功能

关闭一个文件描述符

返回值

成功时返回 0。失败则返回 -1,并设置 errno 为相应的错误标志。

参数

fd:文件描述符

说明

像其它所有系统调用一样,应对 close() 的调用进行错误检查,如下所示:

if (-1 == close(fd)) {

        perror("close error");

        exit(EXIT_FAILURE);

}

以上代码能够捕获的错误有: 

  • 企图关闭一个未打开文件描述符。
  • 多次关闭同一个文件描述符。
  • 捕获特定文件系统在关闭操作时诊断出的错误,例如:NFS(网络文件系统),如果 NFS 出现提交失败,这意味着数据没有抵达远程磁盘,随之将这一错误作为 close() 调用失败的原因传递给应用程序。

例子

以下程序功能:打开 "./log.txt" 文件,然后调用 close() 函数关闭打开的文件

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int flags = O_WRONLY | O_CREAT | O_APPEND; /* 只写,没有该文件则创建,写时从文件内容的末尾附加新内容 */
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /* rw-rw-rw- */
    int fd = open("./log.txt", flags, mode); 
    if (fd < 0) {
        perror("open error");
        exit(EXIT_FAILURE);
    }

    int ret = close(fd); /* 关闭文件描述符 */
    if (ret < 0) {
        perror("close error");
        exit(EXIT_FAILURE);
    }

    printf("process exit success\n");

    return 0;
}

 2. lseek() 函数

        每个打开的文件都有一个与其相关联的当前文件偏移量(current file offset),它通常是一个非负整数,用以度量从文件开始处计算的字节数。

        读写操作都从当前文件偏移量开始,并使偏移量增加所读写的字节数。

        系统默认的情况,当打开一个文件时,除非指定 O_APPEND 选项打开,否则该偏移量被设置为 0。可以调用 lseek() 函数为一个打开的文件设置偏移量。 

头文件和函数声明

#include <sys/types.h>
#include <unistd.h>

typedef long off_t;

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

函数功能

为一个打开的文件设置偏移量

返回值

成功返回新的文件偏移量,失败返回 -1,并设置 errno 为相对应的错误标志。(注意:成功返回新的文件偏移量可能为负数,所以在判断 lseek() 函数一定要谨慎,应该判断返回值是否等于 -1

参数

fd:文件描述符

offset:参数 offset 的含义跟参数 whence 的值有关

  • whence = SEEK_SET 时,则将文件的偏移量设置为文件开始处 offset 个字节,参数 offset 必须为非负数。
  • whence = SEEK_CUR 时,则将文件的偏移量设置为 当前文件的偏移量 + offset 个字节,参数 offset 可以为正数,也可以为负数。
  • whence = SEEK_END 时,则将文件的偏移量设置为 文件长度 + offset 个字节,参数 offset 可以为正数,也可以为负数。

off_t new_offset = lseek(fd, 0, SEEK_SET);         // 将 fd 引用的文件的文件偏移量设置到文件开始处

off_t new_offset = lseek(fd, 0, SEEK_END);        // 将 fd 引用的文件的文件偏移量设置到文件尾部

off_t new_offset = lseek(fd, -1, SEEK_END);       // 将 fd 引用的文件的文件偏移量设置到文件尾部的前一个字节处

 linux 内核中对 SEEK_SET、SEEK_CUR、SEEK_END 的定义如下所示:

#define SEEK_SET	0	/* seek relative to beginning of file */
#define SEEK_CUR	1	/* seek relative to current file position */
#define SEEK_END	2	/* seek relative to end of file */

例子

以下程序功能:打开 "./log.txt" 文件,调用 lseek() 函数将文件偏移量设置为文件尾部,然后从文件尾部开始写入 “hello world\n” 字符串,最后调用 close() 函数关闭打开的文件

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int flags = O_WRONLY | O_CREAT; /* 只写,没有该文件则创建,文件偏移量默认为 0 */
    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /* rw-rw-rw- */
    int fd = open("./log.txt", flags, mode); 
    if (fd < 0) {
        perror("open error");
        exit(EXIT_FAILURE);
    }

    off_t new_offset = lseek(fd, 0, SEEK_END); // 将文件偏移量设置为文件尾部,也可用于获取文件长度(文件所占字节数)的方法
    if (-1 == new_offset) {
        perror("lseek error");
        exit(EXIT_FAILURE);
    }
    off_t length = new_offset;
    printf("before write, file length = %ld\n", length);
    
    char buf[] = "hello world\n"; // strlen(buf) = 12; sizeof(buf) = 13
    ssize_t nwrite = write(fd, buf, strlen(buf));
    if (nwrite < 0) {
        perror("write error");
        exit(EXIT_FAILURE);
    }
    length = lseek(fd, 0, SEEK_END);
    if (-1 == length) {
        perror("lseek error");
        exit(EXIT_FAILURE);
    }
    printf("after write, file length = %ld\n", length);

    if (-1 == close(fd)) {
        perror("close error");
        exit(EXIT_FAILURE);
    }

    return 0;
}

3. read() 函数

头文件和函数声明

#include <unistd.h>

/********************/

/* 32位系统 */

typedef unsigned int size_t ;

typedef int ssize_t ;

/* 64位系统 */

typedef unsigned long size_t ;

typedef long ssize_t;

/********************/

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

函数功能

从文件描述符 fd 引用的文件中请求读取 count 字节的数据并存储到从 buf 开始的缓冲区中

返回值

  • 如果 read() 成功,将返回实际读取到的字节数。
  • 如果遇到文件结尾(EOF)则返回 0。
  • 如果读取失败,则返回 -1,并设置 errno 为相应的错误标志。

说明

一次 read() 调用所读取到的字节数可能会小于请求的字节数

  • 对于普通文件而言,这可能读取到靠近文件尾部了。
  • 对于其它文件类型,比如管道、FIFO、socket 或终端,在不同环境下也会出现读取到的字节数小于请求的字节数。例如,默认情况下,从终端读取字符,遇到换行符(\n),read() 调用就会返回。

参数

fd:文件描述符

buf:存储读取到的数据的首地址

count:请求读取 count 字节数据

4. write() 函数

头文件和函数声明

#include <unistd.h>

/********************/

/* 32位系统 */

typedef unsigned int size_t ;

typedef int ssize_t ;

/* 64位系统 */

typedef unsigned long size_t ;

typedef long ssize_t;

/********************/

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

函数功能

向文件描述符 fd 引用的文件中写入从 buf 开始的缓冲区中 count 字节的数据。

返回值

成功时返回被写入的字节数(若为 0 则表示没有写入数据)。失败则返回 -1,并设置 errno 为相应的错误标志。

参数

fd:文件描述符

buf:要被写入文件的数据在内存中的首地址

count:请求写入 count 字节

说明

如果 write() 调用成功,将会返回实际写入文件的字节数。该返回值可能会小于 count 参数值,这被叫做部分写。

  • 对于磁盘文件来说,造成部分写的原因可能是磁盘已满,或是因为进程资源对文件大小的限制
  • 对于磁盘文件执行 I/O 操作时,write() 调用成功并不能保证已经完成写入磁盘,因为为了减少磁盘活动量和加快 write() 系统调用,内核会缓存磁盘的 I/O 操作

例子

以下程序功能:拷贝一个普通文件。命令行格式:./copyfile_demo log.txt log2.txt

#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define BUF_SIZE 4096

int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("%s input_file out_put_file\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    int ifd = open(argv[1], O_RDONLY); // 只读方式打开
    if (-1 == ifd) {
        fprintf(stderr, "open %s error: %s\n", argv[1], strerror(errno));
        exit(EXIT_FAILURE);
    }

    int flags = O_WRONLY | O_CREAT | O_EXCL; // 只读,创建新文件,O_EXCL:此标志,保证 open() 调用只能创建新文件,如果文件存在则报错
    int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; /* rw-rw-rw- */
    int ofd = open(argv[2], flags, mode);
    if (-1 == ofd)
    {
        if (-1 == close(ifd))
            perror("close error");

        fprintf(stderr, "open %s error: %s\n", argv[2], strerror(errno));
        exit(EXIT_FAILURE);
    }

    char buf[BUF_SIZE] = "";
    ssize_t nread = 0;
    while ((nread = read(ifd, buf, BUF_SIZE)) > 0) {
        if (write(ofd, buf, nread) != nread) {
            if (-1 == close(ifd))
                perror("close error");

            if (-1 == close(ofd))
                perror("close error");

            perror("write error");
            exit(EXIT_FAILURE);
        }
    }

    // 成功 read() 完整个文件,nread = 0
    if (-1 == nread) {
        if (-1 == close(ifd))
            perror("close error");

        if (-1 == close(ofd))
            perror("close error");

        perror("read error");
        exit(EXIT_FAILURE);
    }

    if (-1 == close(ifd))
        perror("close error");

    if (-1 == close(ofd))
        perror("close error");

    printf("copy %s success\n", argv[1]);

    return 0;
}

 注:对实例代码中 open() 函数有疑惑的小伙伴,欢迎浏览我的这篇博文,这里就不再过多阐述。

linux文件I/O之 open() 函数用法_微尘8的博客-CSDN博客

参考:

《UNIX环境高级编程》(第3版)

《Linux-UNIX系统编程手册》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/860400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UNet Model

论文地址 第一阶段 conv2d(33) first conv&#xff1a;5725721 → 57057064 second conv&#xff1a;57057064 → 56856864 代码 # first 33 convolutional layer self.first nn.Conv2d(in_channels, out_channels, kernel_size3, padding1) self.act1 nn.ReLU() # Seco…

渠道订货管理:品牌商建立渠道连接的纽带

当品牌商&#xff08;厂商&#xff09;渠道拓展到一定规模&#xff0c;处理不同渠道交易数据&#xff0c;面对信息流、物流、资金流链路&#xff0c;提升厂商端、经销商端、终端门店的订货体验就会变得尤为重要&#xff0c;特别是一些实力级厂商&#xff0c;渠道下沉能够掌握终…

同步代码块使用错误示范 | 用了synchronized还是出现“超取”问题

记录一下错误&#xff0c;吸取经验&#x1f914;&#x1f60b; 出问题的代码 public class Test {public static void main(String[] args) {new Thread(new Account()).start(); //&#xff01;&#xff01;new Thread(new Account()).start(); //&#xff01;&#xff01;}…

Lecoode有序数组的平方977

题目建议&#xff1a; 本题关键在于理解双指针思想 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 文章讲解&#xff1a;代码随想录 视频讲解&#xff1a; 双指针法经典题目 | LeetCode&#xff1a;977.有序数组的平方_哔哩…

​朋友圈评论截图生成,制作朋友圈网页​

朋友圈头像&#xff0c;上传自己的朋友圈头像&#xff1b;不填默认随机 网名&#xff0c;填写微信昵称&#xff1b; 内容&#xff0c;需要发布的微信正文内容&#xff1b; 截图类型&#xff0c;支持纯文字、图片&#xff08;单张、九宫格&#xff09;、分享网页/公众号文章共…

Webstorm + Egg.js 进行断点调试

Webstorm Egg.js 进行断点调试 1、在工具栏找到编辑配置&#xff0c;创建已运行Node.js 应用程序的调试配置 2、debug调试配置 3、调试 4、查看断点是否起效

【数据结构与算法】十大经典排序算法-希尔排序

&#x1f31f;个人博客&#xff1a;www.hellocode.top &#x1f3f0;Java知识导航&#xff1a;Java-Navigate &#x1f525;CSDN&#xff1a;HelloCode. &#x1f31e;知乎&#xff1a;HelloCode &#x1f334;掘金&#xff1a;HelloCode ⚡如有问题&#xff0c;欢迎指正&#…

易服客工作室:7个优质WordPress LMS线上教育系统插件比较(优点和缺点)

您是否正在为您的 WordPress 网站寻找最好的 LMS 插件&#xff1f;在线学习管理系统 (LMS) 插件允许您使用 WordPress 创建和运行类似 Udemy 的在线课程。 一个完美的 WordPress LMS 插件包括管理在线课程内容、处理订阅、运行和评分测验、接受付款等功能。 在本文中&#xf…

KMP字符串 (简单清晰/Java)

Kmp算法 解决问题&#xff1a; 字符串匹配问题 怎么解决&#xff1f; 前缀表next[]数组 #分析 先看暴力做法&#xff1a; 两层for循环&#xff0c;一层遍历文本串&#xff0c;一层遍历模式串&#xff08;子串&#xff09;对应的每个字符进行匹配&#xff0c;匹配成功就 i &a…

【前端】求职必备知识点2-CSS:优先级、盒子模型、标准流、浮动流、定位流

文章目录 CSS优先级盒子模型标准流、浮动流、定位流标准流浮动流定位流 思维导图 CSS优先级 class类选择器&#xff0c;属性选择器&#xff0c;伪类 的权值为10元素选择器、伪元素选择器权值为1 属性选择器&#xff1a;如&#xff0c;将有title的元素变为红色。 [title] { co…

Python pygame(GUI编程)模块最完整教程(8)

上一篇文章&#xff1a; Python pygame(GUI编程)模块最完整教程&#xff08;7&#xff09;_Python-ZZY的博客-CSDN博客 总目录&#xff1a; README.md Python-ZZY/Python-Pygame最完整教程 - Gitee.com 23 进阶声音操作 参考资料&#xff1a; https://pyga.me/docs/ref/…

在编程下仰望

编程的尽头是数学 数学的尽头是物理 物理的尽头是哲学 哲学的尽头是耶稣 路漫漫其修远兮&#xff0c; 各位码农同仁 好自珍重

Kafka第一课概述与安装

生产经验 面试重点 Broker面试重点 代码,开发重点 67 章了解 如何记录行为数据 1. Kafka概述 1.产生原因 前端 传到日志 日志传到Flume 传到HADOOP 但是如果数据特比大&#xff0c;HADOOP就承受不住了 2.Kafka解决问题 控流消峰 Flume传给Kafka 存到Kafka Hadoop 从Kafka…

geoserver编辑样式 【开发工具QGis的初次使用】

geoserver编辑样式 开发工具配置中文语言 geoserver样式的更改 开发工具 链接: geoserver样式style的更改 链接: QGis开发工具的安装及使用 配置中文语言 setting > options > general > 中文 geoserver样式的更改 链接: geoserver样式style的更改 利用QGIs Q…

3DMAX动力学布料模拟插件DynamoCloth使用方法

3DMAX动力学布料模拟DynamoCloth是一个&#xff08;实时&#xff09;GPU加速的3ds Max Cloth动力学插件&#xff0c;与原生Cloth修改器相比&#xff0c;性能提高了10-100倍。 3DMAX动力学布料模拟是实时的&#xff0c;能够实现实时的自然互动&#xff0c;并将创作过程从试错转…

代码随想录算法训练营第十五天| 层序遍历(即广度优先搜索), 226.翻转二叉树,101. 对称二叉树

层序遍历(即广度优先搜索) 需要借用一个队列来实现&#xff0c;队列先进先出&#xff0c;符合一层一层遍历的逻辑&#xff0c;而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。 思路是先把根节点加入队列&#xff0c;然后在遍历下一层前&#xff0c;先将队列拥有的当前层…

LeetCode150道面试经典题--找出字符串中第一个匹配项的下标(简单)

1.题目 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 2.示例 3.思路 回溯算法&#xff1a;首先将…

【CSS3】CSS3 动画 ⑥ ( 动画属性示例 | 精灵图帧动画效果实现 )

文章目录 一、需求说明二、代码分析1、动画属性2、布局分析3、动画实现 三、完整代码示例 一、需求说明 给定一张精灵图 , 其中有多个 动画帧 对应的图片 , 下图的大小是 1600 x 100 像素 , 截图展示如下 : 实际图片 : 二、代码分析 1、动画属性 使用上图实现 逐帧动画 效果 …

智慧工地云平台源码

智慧工地可以实现对人员管理、施工进度、安全管理、材料管理、设备管理、环境监测等方面的实时监控和管理&#xff0c;提高施工效率和质量&#xff0c;降低安全风险和环境污染。在道路施工中&#xff0c;智慧工地可以实现对道路状况、交通流量、施工进度等方面的实时监控和管理…

Wlan——802.11协议物理层关键技术(OFDM、MIMO、BSS)和CSMA/CD机制的介绍

目录 802.11协议的发展 802.11协议物理层关键技术 信道捆绑技术 OFDM/OFDMA技术 Short-Gi短保护间隔技术 MIMO/MU-MIMO技术 QAM技术 BSS Color快速识别 802.11MAC层关键技术CSMA/CD机制 为什么无线提出了CSMA/CD机制 CSMA/CD的工作机制 CSMA/CD的工作原理 CSMA/CD…