二进制模式打开的文件能否使用fputs与fgets函数?
结论
这段代码里fgets和fputs的使用是错误的,根本没法正确实现两个二进制文件的追加合并。
fgets/fputs不适用的原因
这两个函数从设计之初就是给文本流、字符串读写用的,处理不了包含任意内容的二进制文件,具体问题有三个:
- 读取会被意外截断:
fgets读内容的时候,只要碰到换行符'\n'(对应ASCII值0x0A)就会提前结束当前段的读取。但二进制文件里0x0A就是个普通的数字字节,根本不是什么文本换行标记,遇到就停的逻辑会把连续的二进制数据切得稀碎。 - 部分内容会直接丢失:
fputs写内容的时候,碰到'\0'(对应ASCII值0x00)就会直接停止写入。但二进制数据里0x00是非常常见的普通值,只要读进来的内容里有这个字节,后面的所有数据都不会被写到目标文件里,直接丢失。 - 会额外写入脏数据:代码最后还多写了一个换行符
'\n',这是写文本文件才需要的操作,放到二进制文件里就是多余的无效字节,会直接破坏原文件的内容结构。
顺带提一句,代码里用"rb"、"ab"的二进制模式打开文件,本身就是要处理非文本的二进制内容,再搭配文本专用的fgets、fputs本身逻辑就矛盾了。另外原代码里的fseek(fp, 0, SEEK_END);也是多余的,以追加模式打开的文件,所有写操作默认就会写到文件末尾,不需要手动定位。
正确的替代方案
二进制文件读写应该用fread和fwrite,这两个函数是按指定的字节数读写,不会对任何特殊字节做额外判断和处理,能完整保留所有原始数据。
修正后的参考代码:
/**** Program to APPEND one file after another file ****/ #include <stdio.h> #include <stdlib.h> int main() { FILE *fp, *fc; char data[200]; size_t read_len; fp = fopen("students.DAT", "ab"); if (fp == NULL) { printf("Can't open file"); exit(1); } fc = fopen("pr1.DAT", "rb"); if (fc == NULL) { printf("Can't open file"); fclose(fp); exit(2); } while ((read_len = fread(data, 1, sizeof(data), fc)) > 0) { fwrite(data, 1, read_len, fp); } fclose(fc); fclose(fp); return 0; }
内容的提问来源于stack exchange,提问作者Nitin Bhartiya
相关产品推荐
相关产品推荐

