如何在C语言中使用Linux系统调用向文件开头追加内容
Linux内核与POSIX标准并未提供与O_APPEND对应的、支持直接向文件开头写入内容的open标志位,该需求需要在用户态自行实现,以下是两种常用的可行方案:
方案1:临时文件中转法(生产环境推荐)
该方案通过原子替换操作保证数据安全性,不会因为进程崩溃、系统断电损坏原文件,也支持任意大小的文件:
- 调用
open()以O_RDONLY模式打开原文件 - 调用
open()以O_WRONLY | O_CREAT | O_EXCL模式创建临时文件,权限建议设置为0644(与原文件权限保持一致最佳) - 先将需要写入到文件开头的内容完整写入临时文件
- 循环读取原文件的内容,分批写入到临时文件的末尾(不需要一次性读取整个原文件,内存占用可控)
- 调用
fsync()将临时文件的内容刷入磁盘,避免缓存未写入导致数据丢失 - 调用
rename()系统调用将临时文件原子覆盖原文件 - 关闭原文件和临时文件的文件描述符
核心逻辑示例:
// 错误处理可根据业务场景补充 int orig_fd = open("test.txt", O_RDONLY); int tmp_fd = open("test.txt.tmp", O_WRONLY | O_CREAT | O_EXCL, 0644); // 写入头部内容 char *header = "需要追加到开头的内容"; write(tmp_fd, header, strlen(header)); // 拷贝原文件内容到临时文件 char buf[4096]; ssize_t read_len; while((read_len = read(orig_fd, buf, sizeof(buf))) > 0) { write(tmp_fd, buf, read_len); } fsync(tmp_fd); rename("test.txt.tmp", "test.txt"); close(orig_fd); close(tmp_fd);
方案2:直接修改原文件(仅适合小文件、测试场景)
该方案不需要额外磁盘空间,但不是原子操作,写入中途异常会导致原文件损坏,仅适合文件体积小、数据重要性低的场景:
- 调用
open()以O_RDWR模式打开原文件 - 调用
fstat()获取原文件的大小,申请对应大小的内存缓冲区存储原文件内容 - 读取原文件的全部内容到缓冲区
- 调用
lseek(fd, 0, SEEK_SET)将文件偏移量移动到文件开头 - 先写入需要追加到开头的内容
- 再写入缓冲区存储的原文件内容
- 关闭文件描述符,释放缓冲区内存
注意事项
- 两种方案操作前都建议通过
flock()或fcntl()给原文件加排他锁,避免多进程同时修改导致内容错乱 - 大文件场景下不要使用直接修改原文件的方案,除了内存占用过高外,一旦中途出错原数据无法恢复
- 临时文件建议和原文件放在同一个磁盘分区下,保证
rename()操作是原子的
内容的提问来源于stack exchange,提问作者Tanmay Goyal
相关产品推荐
相关产品推荐

