fread读取文件末尾残留未读内容,增大BUFFSIZE时文件复制不完整如何解决?
问题根本原因
你代码的问题出在fread和fwrite的参数使用逻辑错误,对这两个函数的返回值和计数规则理解有误。fread的函数原型是:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
其中size是单个读取单元的字节大小,nmemb是要读取的单元数量,返回值是实际成功读取的完整单元数量。
你现在的调用方式是fread(buffer, BUFFSIZE, 1, file),也就是把读取单元大小设为BUFFSIZE,每次只读1个单元。这就意味着:
- 只有当文件剩余可读内容≥BUFFSIZE时,才能成功读到1个单元,返回1,进入循环执行写入
- 当文件剩余内容<BUFFSIZE时,fread返回0,循环直接终止,剩下的不足BUFFSIZE的内容既不会被读取,也不会被写入输出文件
当BUFFSIZE设为1的时候,每个单元是1字节,只要文件还有内容就能读到1个单元,返回1,所以能完整复制所有内容,刚好符合你的预期。
修复方案
把读取和写入的单元大小设为1,每次读取最多BUFFSIZE个单元,就可以正确处理最后不足BUFFSIZE的内容:
#define BUFFSIZE 50 int main(void) { void *buffer = malloc(BUFFSIZE); // C标准不需要强制转换malloc返回值 FILE *file = fopen("file.txt", "r"); FILE *outfile = fopen("out.txt", "w"); // 生产环境建议增加文件指针判空逻辑,避免文件打开失败触发崩溃 size_t read_cnt; // 每次读BUFFSIZE个1字节的单元,返回实际读到的字节数 while ((read_cnt = fread(buffer, 1, BUFFSIZE, file)) > 0) // 写入实际读到的字节数,不要固定写BUFFSIZE fwrite(buffer, 1, read_cnt, outfile); free(buffer); fclose(outfile); fclose(file); }
补充建议:如果要复制任意格式的文件(包括二进制文件),建议将fopen的模式改为"rb"和"wb",避免文本模式下的换行符转换导致的文件内容异常。
内容的提问来源于stack exchange,提问作者senya247
相关产品推荐
相关产品推荐

