使用fread读取BMP文件数据不完整且无法打印的技术问题
问题分析与解决
核心问题1:fread 参数顺序错误
fread 的标准原型是:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
参数含义:
size:单个元素的字节大小count:要读取的元素总数
你的代码中写反了这两个参数:
f_size = fread(str, 8, sizeof(char), fptr_stego);
这段代码会尝试读取1个大小为8字节的元素,而非8个1字节的字符。一旦文件中当前位置无法提供完整的8字节连续数据(或受文本模式干扰),就会返回小于1的结果,这就是你只读到1字节的直接原因。
正确写法应为:
f_size = fread(str, sizeof(char), 8, fptr_stego);
核心问题2:以文本模式打开二进制文件
BMP是二进制格式文件,你用"r"文本模式打开时,会触发系统的文本转换逻辑:
- Windows下会自动把
\r\n转换为\n,破坏字节偏移的准确性 - 任何位置的
0x1A(ASCII终止符)会被视为文件结束,提前终止读取
必须改用二进制模式打开:
fptr_stego = fopen("stego.bmp", "rb");
附加问题:不可打印字符的输出
你用%c打印str[0],如果该字节是不可打印字符(比如0x00、控制字符等),终端不会显示任何内容。可以改用十六进制格式查看实际字节值:
printf("First byte data: 0x%02X\n", (unsigned char)str[0]);
修正后的完整代码
#include<stdio.h> int main() { FILE *fptr_stego; FILE *fptr_text; size_t f_size = 0; char str[8]; // 以二进制模式打开图像文件 fptr_stego = fopen("stego.bmp", "rb"); if(fptr_stego == NULL) { printf("FAILED to open stego file\n"); return 0; } fptr_text = fopen("decode.txt", "w"); if(fptr_text == NULL) { printf("FAILED to open text file\n"); return 0; } printf("Successfully opened both files\n"); // 验证指针移动是否成功 if(fseek(fptr_stego, 54, SEEK_SET) != 0) { printf("fseek failed\n"); return 0; } printf("File pointer location before reading %ld\n", ftell(fptr_stego)); // 修正fread参数顺序,读取8个char元素 f_size = fread(str, sizeof(char), 8, fptr_stego); if(f_size != 8) { printf("Unable to fetch 8 bytes\n%ld bytes read at %ld position\n", f_size, ftell(fptr_stego)); printf("First byte data: 0x%02X\n", (unsigned char)str[0]); return 0; } // 将读取的内容写入文本文件 fwrite(str, sizeof(char), 8, fptr_text); fclose(fptr_stego); fclose(fptr_text); printf("Data read successfully\n"); return 0; }
额外验证建议
- 用
hd stage.bmp确认第54到61字节的内容,修正后的代码应能正确读取这些字节 - 若仍有问题,可检查
fseek的返回值,确认指针是否成功移动到目标位置
内容的提问来源于stack exchange,提问作者Siddharth Singh
相关产品推荐
相关产品推荐

