大家好我是小刘。最近在写代码时又被文件操作坑了一把用 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 个实战坑点,让你写代码再也不翻车
发布时间:2026/6/14 19:31:15
大家好我是小刘。最近在写代码时又被文件操作坑了一把用 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 个坑我在实战中都踩过每一个都让我印象深刻。写文件操作核心就是 “严谨”检查每一次打开、每一次读写、每一次关闭。如果你在开发中也遇到过类似的问题欢迎在评论区留言交流我们一起避坑共同进步。个人总结水平有限欢迎大家交流指正共同进步。