C++笔记-文件IO-<fcntl.h>

<fcntl.h> 文件控制

一、是什么

<fcntl.h> = file control,提供 C 风格的文件系统调用:

内容 用途
open() 打开 / 创建文件
O_* 标志 控制打开方式
fcntl() 修改 fd 属性

二、open 原型

cpp 复制代码
int open(const char *pathname, int flags, mode_t mode);
参数 含义
pathname 文件路径
flags 打开方式(O_RDONLYO_CREAT 等)
mode 权限,只在 O_CREAT 时用,如 0644
返回 成功 fd >= 0,失败 -1

三、常用标志

标志 含义
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
O_CREAT 不存在就创建
O_APPEND 追加写,每次写到末尾
O_TRUNC 打开时清空
O_EXCL 配合 O_CREAT,文件已存在则失败
O_NONBLOCK 非阻塞

多个标志用 | 组合:

cpp 复制代码
open("data.log", O_CREAT | O_WRONLY | O_APPEND, 0644);

四、权限 0644

三位八进制:

复制代码
6 4 4
│ │ └─ 其他人:r--
│ └─── 组:r--
└───── 拥有者:rw-
数字 权限
4
2
1 执行
6 读+写
7 读+写+执行

五、读 / 写 / 关闭

需要 #include <unistd.h>

unistd=Unix Standard

cpp 复制代码
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
int close(int fd);
返回值 含义
read > 0 实际读到的字节数
read = 0 文件读完 / 对端关闭
read = -1 出错
write > 0 实际写入的字节数
write = -1 出错

注意:write 可能写不全,大消息要循环写:

cpp 复制代码
size_t total = 0;
while (total < len) {
    ssize_t n = write(fd, buf + total, len - total);
    if (n <= 0) break;
    total += n;
}

六、落盘 fsync

需要 #include <unistd.h>

cpp 复制代码
fsync(fd);
  • 强制把内核缓冲区写到磁盘
  • 防崩溃丢数据
  • 比普通 write 慢很多

WAL (预写日志)必须用:

cpp 复制代码
write(fd, log.c_str(), log.size());
fsync(fd);              // 确保真落盘

七、定位 lseek

cpp 复制代码
off_t lseek(int fd, off_t offset, int whence);
whence 含义
SEEK_SET 从开头
SEEK_CUR 从当前位置
SEEK_END 从末尾
cpp 复制代码
lseek(fd, 0, SEEK_SET);   // 回到开头

八、最常用模板

追加写 + 落盘

cpp 复制代码
int fd = open("data.log", O_CREAT | O_WRONLY | O_APPEND, 0644);
if (fd < 0) { /* 出错 */ }

std::string log = "SET key value\n";
write(fd, log.c_str(), log.size());
fsync(fd);
close(fd);

只读打开

cpp 复制代码
int fd = open("data.txt", O_RDONLY);
char buf[1024];
ssize_t n;
while ((n = read(fd, buf, sizeof(buf))) > 0) {
    // 处理 buf 前 n 字节
}
close(fd);

九、常见坑

说明
open 返回 -1 要检查 不检查后面全崩
write 可能写不全 大消息要循环
fsync 很慢 别每条都调,重要才调
O_APPEND 保证原子追加 多线程写同一 fd 安全
fd 用完要 close 否则泄漏
read 返回 0 是正常结束,不是错误

十、和 <fstream> 对比

<fcntl.h>(C 风格) <fstream>(C++ 风格)
类型 int fd ifstream / ofstream
打开 open("a.txt", O_RDONLY) ifstream in("a.txt")
read(fd, buf, n) getline(in, line) / in >> x
write(fd, buf, n) out << "hi"
关闭 close(fd) 自动 / in.close()
落盘 fsync(fd)
非阻塞 fcntl
网络 fd ✅ 同一套
逐行读 ❌ 自己处理 getline
格式化输出 <<
跨平台 Linux / POSIX ✅ 全平台
底层 系统调用 封装系统调用

十一、怎么选

场景 用哪个
读文本、逐行处理 ifstream + getline
写文本 ofstream
fsync 落盘 open + write + fsync
网络 socket read / write
要非阻塞 fcntl
跨平台 fstream

十二、总结

<fcntl.h> 是 C 风格底层文件 IO:open 打开,read/write 读写,fsync 落盘,close 关闭。

要落盘、要网络 fd、要非阻塞 → 用它;日常读文本 → 用 <fstream>

相关推荐
Smileyqp沛沛3 小时前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车3 小时前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光4 小时前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
吞下星星的少年·-·4 小时前
C++ 萌新语法入门篇
c++·算法比赛
霍霍的袁4 小时前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
another heaven5 小时前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
程序猿编码5 小时前
告别改源码适配模型:纯 C++ 可配置 LLM 推理引擎,全格式全结构兼容
c++·大模型·llm·推理引擎
此生决int5 小时前
深入理解C++系列(20)——C++11(下)
开发语言·c++
郝学胜-神的一滴5 小时前
C++20模板元编程 07:吃透名称绑定与编译期递归核心原理
c++·程序人生·vs·模板元