C语言使用fread读取二进制文件返回0导致循环终止如何解决
问题原因
核心问题是fread的参数使用错误,该函数的原型为:
size_t fread(void *restrict ptr, size_t size, size_t nmemb, FILE *restrict stream);
size:单个读取单元的字节大小nmemb:要读取的单元总数量- 返回值是成功读取的单元数量,不是字节总数
你代码中sizeof(buffer)已经等于positionX(因为你定义的是unsigned char buffer[positionX],缓冲区总大小就是整个文件的大小),此时第二个参数传sizeof(buffer)、第三个参数传positionX,相当于要求fread读取总大小为positionX * positionX字节的内容,远大于实际文件的大小,自然读取失败返回0。
修复方案
修改fread的参数即可,有两种常用写法:
- 按字节为单元读取:
// 每个单元1字节,读positionX个单元,返回值是成功读取的字节数 size_t readed = fread(buffer, 1, positionX, file);
- 按整个缓冲区为单元读取:
// 每个单元大小是整个缓冲区大小,读1个单元,返回值为1表示读取成功 size_t readed = fread(buffer, sizeof(buffer), 1, file); // 此时遍历内容用positionX作为循环上限即可
另外补充两个优化点:
- 变长数组(VLA)在栈上分配大内存容易触发栈溢出,文件较大时更推荐用
malloc在堆上分配缓冲区,使用完后调用free释放即可 - 读取完成后记得调用
fclose(file)关闭文件句柄,避免资源泄漏
完整修复后代码示例
#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: 请传入要读取的文件路径\n"); return 1; } FILE *file = fopen(argv[1], "rb"); if (file == NULL) { printf("无法打开文件\n"); return 1; } fseek(file, 0, SEEK_END); long positionX = ftell(file); rewind(file); printf("文件大小:%ld\n", positionX); unsigned char *buffer = malloc(positionX); if (buffer == NULL) { printf("内存分配失败\n"); fclose(file); return 1; } size_t readed = fread(buffer, 1, positionX, file); printf("成功读取%zu字节\n", readed); for(size_t i = 0; i < readed; i++) { printf("%02x ", buffer[i]); } free(buffer); fclose(file); return 0; }
内容的提问来源于stack exchange,提问作者user1950241
相关产品推荐
相关产品推荐

