语言文件操作避坑指南:10 个实战坑点,让你写代码再也不翻车

大家好,我是小刘。最近在写代码时,又被文件操作坑了一把:用 fseek + ftell 拿到文件大小后,直接 fread,结果复制出来的文件是空的。

相信很多朋友在写文件复制、批量处理时,也踩过类似的坑:文件为空、程序崩溃、数据损坏……

今天我把自己实战中踩过的 10 个坑一次性整理出来,帮你少走弯路,以后写文件操作再也不翻车。

1. 忘记把文件指针移回开头

坑点:用 fseek(fp, 0, SEEK_END) + ftell 拿到文件大小后,直接 fread。

后果:文件指针还在末尾,读出来是空数据,复制的文件为空。

解决:在 fread 前加一行:

fseek(fp, 0, SEEK_SET); // 回到文件开头
// 或用 rewind(fp); 效果相同

2. fread / fwrite 传参不写地址

坑点:

char ch;
fread(ch, 1, 1, fp); // 错误!直接传变量

后果:类型不匹配,程序崩溃或传参失败。

解决:传变量的地址(数组名本身是地址,可直接传):

fread(&ch, 1, 1, fp); // 正确

3. 搞反 fread 参数顺序,误解返回值

坑点:

fread(buf, 32, 1, fp); // 返回值是“块数”,不是字节数
if (num < 32) // 逻辑永远成立,循环提前退出

后果:文件复制不完整。

解决:fread 参数顺序是 (缓冲区地址, 块大小, 块数, 文件指针)。想读多少字节,就把块大小设为 1,块数设为字节数:

size_t num = fread(buf, 1, 32, fp); // 返回实际读到的块数(即字节数)
if (num < 32) {
    // 处理读取不完整的情况
}

4. 用文本模式复制二进制文件

坑点:用 "r" / "w" 打开文件复制图片、可执行文件。

后果:Windows 下 \n 被自动转成 \r\n,文件损坏。(Linux系统不区分,为了可移植,建议加上)

解决:始终用二进制模式:

FILE *fp = fopen("file", "rb"); // 读二进制
FILE *fp = fopen("file", "wb"); // 写二进制

5. malloc 后不检查是否成功

坑点:

char *buf = malloc(size);
fread(buf, 1, size, fp); // 如果malloc失败,buf是NULL

后果:程序崩溃。

解决:

if (buf == NULL) {
    perror("malloc failed");
    return -1;
}

6. malloc 申请的内存不 free

坑点:程序结束前不释放内存。

后果:内存泄漏,长时间运行后系统资源耗尽。

解决:

free(buf);
buf = NULL; // 好习惯,避免野指针

7. 打开文件后不检查是否成功

坑点:

FILE *fp = fopen("not_exist.txt", "r");
fread(...); // 如果文件不存在,fp是NULL

后果:程序崩溃。

解决:

if (fp == NULL) {
    perror("fopen failed");
    return -1;
}

8. 打开的文件不关闭

坑点:只 fopen,不 fclose。

后果:文件描述符泄漏,数据可能未写入磁盘。

解决:

fclose(fp);
fp = NULL;

9. 大文件一次性读完

坑点:对几 GB 的大文件用 malloc(size) 一次性读尽。

后果:内存不足,程序崩溃。

解决:用固定大小缓冲区循环读写(推荐 4KB,与文件系统页大小对齐,效率最高):

#define BUF_SIZE 4096
char buf[BUF_SIZE];
size_t num;
while ((num = fread(buf, 1, BUF_SIZE, fp1)) > 0) {
    fwrite(buf, 1, num, fp2);
}

10. 忽略 fread / fwrite 的返回值

坑点:只调用函数,不检查返回的字节数。

后果:读写不完整,数据损坏却不自知。

解决:读多少,就写多少,严格判断:

size_t read_num = fread(buf, 1, size, fp);
if (read_num < size) {
    if (feof(fp)) {
        // 到达文件末尾,正常结束
    } else if (ferror(fp)) {
        perror("fread failed"); // 发生错误
    }
}

这 10 个坑,我在实战中都踩过,每一个都让我印象深刻。写文件操作,核心就是 “严谨”:检查每一次打开、每一次读写、每一次关闭。

如果你在开发中也遇到过类似的问题,欢迎在评论区留言交流,我们一起避坑,共同进步。

个人总结,水平有限,欢迎大家交流指正,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值