Linux-C/C++--文件 I/O 基础
在 Linux 中,文件 I/O 是指通过系统调用或命令对文件进行的输入输出操作。Linux 操作系统提供了强大的文件操作功能,使得用户和程序可以方便地对文件进行读取、写入、修改和管理。文件 I/O 指的是对文 件的输入/输出操作,说白了就是对文件的读写操作;Linux 下一切皆文件,文件作为 Linux 系统设计思想的核心理念,在 Linux 系统下显得尤为重要,所以对文件的 I/O 操作既是基础也是最重要的部分。
本章先向大家介绍 Linux 系统下文件描述符的概念,随后会逐一讲解构成通用 I/O 模型的系统调用,譬 如打开文件、关闭文件、从文件中读取数据和向文件中写入数据以及这些系统调用涉及的参数等内容。
本章将会讨论如下主题内容。
文件描述符的概念;
打开文件 open()、关闭文件 close();
写文件 write()、读文件 read();
文件读写位置偏移量。
一、文件IO示例
我们先来看一个简单地文件读 写示例,主要涉及到 4 个函数:open()、read()、write()以及 close(),应用程序代码如下所示:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{char buff[1024];int fd1, fd2;int ret;/* 打开源文件 src_file(只读方式) */fd1 = open("./src_file", O_RDONLY);if (-1 == fd1)return fd1;/* 打开目标文件 dest_file(只写方式) */fd2 = open("./dest_file", O_WRONLY);if (-1 == fd2) {ret = fd2;goto out1;}/* 读取源文件 1KB 数据到 buff 中 */ret = read(fd1, buff, sizeof(buff));if (-1 == ret)goto out2;/* 将 buff 中的数据写入目标文件 */ret = write(fd2, buff, sizeof(buff));if (-1 == ret)goto out2;ret = 0;
out2:/* 关闭目标文件 */close(fd2);
out1:/* 关闭源文件 */close(fd1);return ret;
}
这段代码非常简单明了,代码所要实现的功能在注释当中已经描述得很清楚了,从源文件 src_file 中读 取 1KB 数据,然后将其写入到目标文件 dest_file 中(这里假设当前目录下这两个文件都是存在的);在进 行读写操作之前,首先调用 open 函数将源文件和目标文件打开,成功打开之后再调用 read 函数从源文件中 读取 1KB 数据,然后再调用 write 函数将这 1KB 数据写入到目标文件中,至此,文件读写操作就完成了, 读写操作完成之后,最后调用 close 函数关闭源文件和目标文件。
接下来我们给大家详细介绍这些函数以及相关的内容。
二、文件描述符(File Descriptor)
在 Linux 中,所有的文件操作都是通过文件描述符(file descriptor)来进行的。文件描述符是一个非负整数,它指向内核中的文件表项。每当你打开一个文件时,操作系统会返回一个文件描述符。
-
标准输入(stdin):文件描述符 0
-
标准输出(stdout):文件描述符 1
-
标准错误(stderr):文件描述符 2
对于普通文件,当你通过 open() 系统调用打开文件时,会返回一个文件描述符。程序可以通过这个描述符来读写文件。
调用 open 函数会有一个返回值,譬如示例代码 2.1.1 中的 fd1 和 fd2,这是一个 int 类型的数据,在 open 函数执行成功的情况下,会返回一个非负整数,该返回值就是一个文件描述符(file descriptor),这说明文 件描述符是一个非负整数;对于 Linux 内核而言,所有打开的文件都会通过文件描述符进行索引。
当调用 open 函数打开一个现有文件或创建一个新文件时,内核会向进程返回一个文件描述符,用于指 代被打开的文件,所有执行 IO 操作的系统调用都是通过文件描述符来索引到对应的文件,譬如示例代码 2.1.1 中,当调用 read/write 函数进行文件读写时,会将文件描述符传送给 read/write 函数,所以在代码中, fb1 就是源文件 src_file 被打开时所对应的文件描述符,而 fd2 则是目标文件 dest_file 被打开时所对应的文件描述符。
ulimit -n 
三、打开文件(open)
在 Linux 中,可以通过 open() 系统调用打开文件,返回一个文件描述符。该系统调用的语法如下:
int open(const char *pathname, int flags, mode_t mode);
pathname:文件路径flags:打开文件的方式(例如只读、只写、创建等)mode:文件权限(如果文件是新创建的,指定文件的权限)
常用的 flags 参数包括:
O_RDONLY:只读模式O_WRONLY:只写模式O_RDWR:读写模式O_CREAT:如果文件不存在则创建文件O_TRUNC:打开文件时截断文件为 0 长度(如果文件已存在)
在 Linux 系统下,可以通过 man 命令(也叫 man 手册)来查看某一个 Linux 系统调用的帮助信息,man 命令可以将该系统调用的详细信息显示出来,譬如函数功能介绍、函数原型、参数、返回值以及使用该函数所需包含的头文件等信息;man 更像是一份帮助手册,所以也把它称为 man 手册,当我们需要查看某个系统调用的功能介绍、使用方法时,不用在上网到处查找,直接通过 man 命令便可以搞定,man 命令用法如下所示:
man 2 open

四、写入文件(write)
写入文件内容通过 write() 系统调用来实现。write() 会将数据从缓冲区写入到指定的文件描述符对应的文件中。
#include <unistd.h
ssize_t write(int fd, const void *buf, size_t count);
fd:文件描述符buf:包含要写入数据的缓冲区count:要写入的字节数
返回值:如果成功将返回写入的字节数(0 表示未写入任何字节),如果此数字小于 count 参数,这不是错误,譬如磁盘空间已满,可能会发生这种情况;如果写入出错,则返回-1。
五、读取文件(read)
读取文件内容通常通过 read() 系统调用实现。read() 从指定的文件描述符中读取数据到缓冲区中。
#include <unistd.h
ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符buf:缓冲区,用于存储读取的数据count:要读取的字节数
返回值:如果读取成功将返回读取到的字节数,实际读取到的字节数可能会小于 count 参数指定的字节 数,也有可能会为 0,譬如进行读操作时,当前文件位置偏移量已经到了文件末尾。实际读取到的字节数少于要求读取的字节数,譬如在到达文件末尾之前有 30 个字节数据,而要求读取 100 个字节,则 read 读取成功只能返回 30;而下一次再调用 read 读,它将返回 0(文件末尾)
六、关闭文件(close)
文件使用完毕后,应该通过 close() 系统调用关闭文件描述符,释放系统资源。
#include <unistd.h>
int close(int fd);
fd:文件描述符
返回值:成功时返回 0,失败时返回 -1。
除了使用 close 函数显式关闭文件之外,在 Linux 系统中,当一个进程终止时,内核会自动关闭它打开 的所有文件,也就是说在我们的程序中打开了文件,如果程序终止退出时没有关闭打开的文件,那么内核会 自动将程序中打开的文件关闭。很多程序都利用了这一功能而不显式地用 close 关闭打开的文件。
七、lseek
在 C 语言中,lseek() 函数用于在打开的文件中进行文件指针的位置移动。它允许我们在文件中进行随机访问,指定新的文件偏移量(即文件指针的当前位置)。该函数可以向前、向后移动文件指针,甚至使其跳转到文件的任意位置。
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
-
fd:文件描述符。表示一个已打开文件的文件描述符。可以通过open()系统调用返回的文件描述符来获取。 -
offset:相对于whence的偏移量。它表示新的文件指针的位置。如果whence的值为SEEK_SET,则偏移量是相对于文件开头的;如果whence的值为SEEK_CUR,则偏移量是相对于当前文件指针的位置;如果whence的值为SEEK_END,则偏移量是相对于文件结尾的位置。 -
whence:指明偏移的起始位置。可以是以下值之一:-
SEEK_SET:表示从文件的起始位置开始计算偏移量。 -
SEEK_CUR:表示从当前文件指针位置开始计算偏移量。 -
SEEK_END:表示从文件的结尾位置开始计算偏移量。
-
返回值:成功时,返回新的文件偏移量(以字节为单位)。失败时,返回 -1,并且设置 errno 以指示错误原因
错误码:常见的错误包括:
-
EINVAL:传入的whence值无效。 -
ESPIPE:文件描述符不支持lseek()操作(例如,套接字文件描述符)
使用示例
以下是一个使用 lseek() 的简单示例,它演示了如何在文件中移动文件指针,并进行读取操作
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>int main() {// 打开文件int fd = open("example.txt", O_RDWR | O_CREAT, 0644);if (fd == -1) {perror("Failed to open file");return 1;}// 写入一些数据write(fd, "Hello, world!", 13);// 使用 lseek 定位到文件的开头off_t offset = lseek(fd, 0, SEEK_SET);if (offset == -1) {perror("Failed to seek to the beginning");close(fd);return 1;}// 读取文件内容char buffer[20];ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);if (bytes_read == -1) {perror("Failed to read file");close(fd);return 1;}// 确保字符串以 '\0' 结尾buffer[bytes_read] = '\0';printf("File content: %s\n", buffer);// 使用 lseek 定位到文件末尾offset = lseek(fd, 0, SEEK_END);if (offset == -1) {perror("Failed to seek to the end");close(fd);return 1;}// 文件指针现在在文件的末尾,写入新的数据write(fd, " Goodbye!", 9);// 关闭文件close(fd);return 0;
}
解释
-
打开文件:首先,我们通过
open()打开文件example.txt,并确保该文件可以读写。如果文件不存在,则创建文件。 -
写入数据:写入字符串 "Hello, world!" 到文件中。
-
文件指针移动到文件开头:使用
lseek(fd, 0, SEEK_SET)将文件指针移动到文件开头。 -
读取文件内容:从文件中读取数据并输出。
-
文件指针移动到文件末尾:使用
lseek(fd, 0, SEEK_END)将文件指针移动到文件末尾。 -
写入更多数据:在文件的末尾添加新的数据。
-
关闭文件:完成文件操作后关闭文件描述符
本小节内容到此结束。2025年决定把linux-C/C++相关内容重温分享给大家。欢迎留言评论,感谢!!!
相关文章:
Linux-C/C++--文件 I/O 基础
在 Linux 中,文件 I/O 是指通过系统调用或命令对文件进行的输入输出操作。Linux 操作系统提供了强大的文件操作功能,使得用户和程序可以方便地对文件进行读取、写入、修改和管理。文件 I/O 指的是对文 件的输入/输出操作,说白了就是对文件的读…...
HarmonyOS NEXT开发进阶(六):HarmonyOS NEXT实现嵌套 H5 及双向通信
文章目录 一、前言二、鸿蒙应用加载Web页面2.1 加载网络地址页面2.2 加载本地H5页面 三、实现Web组件 H5 层与鸿蒙应用层进行相互通讯3.1 鸿蒙应用向 H5 页面发送数据3.2 H5页面向鸿蒙应用发送数据 四、拓展阅读 一、前言 随着HarmonyOS NEXT的快速发展,越来越多的…...
【Flink系列】4. Flink运行时架构
4. Flink运行时架构 4.1 系统架构 Flink运行时架构——Standalone会话模式为例 1)作业管理器(JobManager) JobManager是一个Flink集群中任务管理和调度的核心,是控制应用执行的主进程。也就是说,每个应用都应该被…...
动态主机配置协议 (DHCPv4)介绍,详细DHCP协议学习笔记
定义 动态主机配置协议 (DHCP) 是一种用于集中对用户 IPv4 地址进行动态管理和配置的技术。为与 IPv6 动态主机配置协议 (DHCPv6) 进行区分,本文统一将动态主机配置协议称为 DHCPv4。 DHCPv4 协议由 RFC 2131 定义,采用客户端/服务器通信模式ÿ…...
Vue.js组件开发-如何处理跨域请求
在Vue.js组件开发中,处理跨域请求(CORS,即跨来源资源共享)通常不是直接在Vue组件中解决的,而是需要后端服务器进行相应的配置,以允许来自不同源的请求。不过,前端开发者也需要了解一些基本的COR…...
【C++】构造函数与析构函数
写在前面 构造函数与析构函数都是属于类的默认成员函数! 默认成员函数是程序猿不显示声明定义,编译器会中生成。 构造函数和析构函数的知识需要建立在有初步类与对象的基础之上的,关于类与对象不才在前面笔记中有详细的介绍:点我…...
Agent区别于MOE和RAG的核心; Agent(智能体)、RAG和MOE区别
Agent区别于MOE(专家混合模型)和RAG(检索增强生成)的核心 目录 Agent区别于MOE(专家混合模型)和RAG(检索增强生成)的核心自主性与决策能力环境交互与学习能力多模态感知与处理能力Agent(智能体)、RAG(检索增强生成)和MOE(专家混合模型)区别Agent(智能体)RAG(检…...
【PCL】Segmentation 模块—— 欧几里得聚类提取(Euclidean Cluster Extraction)
1、简介 PCL 的 Euclidean Cluster Extraction(欧几里得聚类提取) 是一种基于欧几里得距离的点云聚类算法。它的目标是将点云数据分割成多个独立的簇(clusters),每个簇代表一个独立的物体或结构。该算法通过计算点与点…...
LuaJIT Garbage Collector Algorithms
Explain 本篇文章是对Make Pall发表wili内容《LuaJIT 3.0 new Garbage Collector》的翻译和扩展,因为原文是对LuaJIT 2.x GC重要功能的简介和对LuaJIT 3.0 new GC的工作计划,所以它并不是系统性介绍GC的文章。希望以后能有精力系统性的对LuaJIT 2.x GC做…...
go采集注册表
package mainimport ("fmt""golang.org/x/sys/windows/registry""log""os""strconv""strings" )func USBSTOR_Enum() {// 打开注册表键keyPath : SYSTEM\CurrentControlSet\Services\USBSTOR\Enumk, err : regist…...
软件工程师欧以宁:引领无人机导航与物联网安全的技术革新
在科技日新月异的今天,软件工程师欧以宁凭借卓越的技术能力和前瞻性的创新思维,成为了无人机自主导航和物联网安全领域的佼佼者。作为一名深耕技术前沿的专家,欧以宁不仅推动了无人机导航技术的突破性进展,还为智能家居和物联网的安全架构提供了全新的解决方案。她的研究成果,以…...
从零开始:Gitee 仓库创建与 Git 配置指南
引言 Git 是一款广泛使用的版本控制工具,它能够帮助开发者在开发过程中高效地管理代码的版本。而 Gitee(码云)是国内知名的 Git 托管平台,它提供了强大的代码托管、团队协作和项目管理功能。如果你是 Git 和 Gitee 的新手&#x…...
浅谈计算机网络02 | SDN控制平面
计算机网络控制平面 一、现代计算机网络控制平面概述1.1 与数据平面、管理平面的关系1.2 控制平面的发展历程 二、控制平面的关键技术剖析2.1 网络层协议2.1.1 OSPF协议2.1.2 BGP协议 2.2 SDN控制平面技术2.2.1 SDN架构与原理2.2.2 OpenFlow协议2.2.3 SDN控制器 一、现代计算机…...
在 QNAP NAS中使用 Container Station 运行 Docker 的完整指南
QNAP 为用户提供了一个名为 Container Station 的应用,它在 QNAP NAS 上将 Docker 和 LXC 结合在一起,通过图形化界面,让用户更轻松地在 NAS 上管理容器。本文将带你一步步了解如何在 QNAP NAS 上安装和使用 Container Station,以…...
XML在线格式化 - 加菲工具
XML在线格式化 打开网站 加菲工具 选择“XML 在线格式化” 输入XML,点击左上角的“格式化”按钮 得到格式化后的结果...
大数据学习(34)-mapreduce详解
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦ᾑ…...
代码合并冲突解决push不上去的问题
环境:【IntelliJ IDEA】 【Gerrit】 1、错误信息 代码合并,迭代1合并到迭代2,解决冲突后,依然push不上去,报错信息如下: remote: Processing changes: refs: 1 remote: Processing changes: refs…...
万字长文介绍ARINC 653,以及在综合模块化航空电子设备(IMA)中的作用
文章目录 一、引言二、ARINC 653背景三、整体系统架构四、应用/执行(APEX)接口五、ARINC 653 RTOS内部机制六、健康监测功能七、软件应用八、ARINC 653现状九、总结 一、引言 在现代航空领域,综合模块化航空电子设备(IMA…...
MySQL 与 Redis 数据一致性 2
1. 强一致还是最终一致?2. 先写 MySQL 还是先写Redis?case 1 3. 缓存(Redis)更新还是清除?更新策略更新策略会有数据不一致问题?数据不一致的概率与影响如果使用监听binlog更新数据还会出现数据不一致问题?binlog的消费问题 使用消息队列行不行?其他方案总结: 数据不一致…...
MySQL程序之:使用类似URI的字符串或键值对连接到服务器
本节介绍使用类似URI的连接字符串或键值对来指定如何为MySQLShell等客户端建立到MySQL服务器的连接。 以下MySQL客户端支持使用类似URI的连接字符串或键值对连接到MySQL服务器: MySQL Shell实现X DevAPI的MySQL连接器 本节记录了所有有效的类似URI的字符串和键值…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
