You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

open()系统调用中O_TRUNC未实际清空文件内容的问题

解决O_TRUNC未清空文件导致写入后残留内容的问题

嘿,我太懂你这个坑了!当初我第一次用O_TRUNC参数的时候也踩过类似的雷,看到文件里残留的字符简直一脸懵。咱们来拆解一下问题到底出在哪,以及怎么解决:

问题根源

你看到最终文件是81而不是预期的8,核心原因是:
O_TRUNC的作用是在打开文件的瞬间就把整个文件内容清空,但你的操作逻辑应该是先打开文件读取原有内容(这时候没加O_TRUNC,所以文件内容还在),然后直接写入新值——这种情况下,新写入的内容只会覆盖文件开头对应长度的字节,剩下的原有字符自然就保留下来了。

举个例子:原文件是11(两个字节),你写入8(一个字节),只会把第一个1改成8,第二个1还留在文件里,所以结果就是81。

两种解决方案

方案一:分两步读写(最安全推荐)

先以只读模式打开文件读取内容,关闭后再以清空模式打开写入新值,这样能彻底避免残留问题:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    // 1. 读取原有内容
    int fd_read = open("test.txt", O_RDONLY);
    if (fd_read == -1) {
        perror("打开读取文件失败");
        return 1;
    }
    char buf[10];
    ssize_t bytes_read = read(fd_read, buf, sizeof(buf)-1);
    close(fd_read);
    if (bytes_read <= 0) {
        perror("读取文件失败");
        return 1;
    }
    buf[bytes_read] = '\0'; // 确保字符串正确终止

    // 计算新数值
    int num = atoi(buf) - 3;

    // 2. 清空并写入新内容
    int fd_write = open("test.txt", O_WRONLY | O_TRUNC | O_CREAT, 0644);
    if (fd_write == -1) {
        perror("打开写入文件失败");
        return 1;
    }
    char write_buf[10];
    int len = snprintf(write_buf, sizeof(write_buf), "%d", num);
    write(fd_write, write_buf, len);
    close(fd_write);

    return 0;
}

方案二:单文件描述符操作(适合需保持文件打开的场景)

如果必须用同一个文件描述符完成读写,可以在读取内容后,用ftruncate()手动清空文件,再定位到开头写入:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("test.txt", O_RDWR);
    if (fd == -1) {
        perror("打开文件失败");
        return 1;
    }

    // 读取原有内容
    char buf[10];
    ssize_t bytes_read = read(fd, buf, sizeof(buf)-1);
    if (bytes_read <= 0) {
        perror("读取文件失败");
        close(fd);
        return 1;
    }
    buf[bytes_read] = '\0';
    int num = atoi(buf) - 3;

    // 清空文件并移动到开头
    if (ftruncate(fd, 0) == -1) {
        perror("清空文件失败");
        close(fd);
        return 1;
    }
    lseek(fd, 0, SEEK_SET);

    // 写入新内容
    char write_buf[10];
    int len = snprintf(write_buf, sizeof(write_buf), "%d", num);
    write(fd, write_buf, len);

    close(fd);
    return 0;
}

关键注意点

  • 千万别用O_RDWR | O_TRUNC打开文件来同时读写——O_TRUNC会在打开瞬间清空文件,你根本读不到原来的内容。
  • 只要新写入的内容长度比原文件短,就必须主动清空或截断文件,否则一定会残留旧内容。

内容的提问来源于stack exchange,提问作者Sebastian Oliva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:39:40