读取BMP文件BITMAPFILEHEADER时输出ASCII而非数字的解决方法
问题原因
你遇到的问题本质是数据类型解析方式不对:
char是字符类型,std::cout输出char数组时,会把每个字节当作ASCII字符渲染,而BITMAPFILEHEADER里的大部分数据是二进制数值(比如文件大小、数据区偏移量这类多字节整数),并非可打印ASCII字符,所以会显示乱码或奇怪符号。- 你用默认的文本模式打开文件,Windows下文本模式会自动转换换行符(将
\r\n替换为\n),这会破坏BMP的二进制结构,导致读取的数据不准确。 char数组没有终止符,std::cout输出时可能遇到随机的\0截断输出,结果更不可控。
解决方法
1. 先修正文件打开模式
必须以二进制模式打开BMP文件,避免文本模式的换行符转换:
file.open(path, std::ios::binary);
2. 方式一:直接输出每个字节的数值
如果你只是想查看每个字节的十六进制/十进制数值,可以遍历数组,把每个字节当作无符号数值输出:
#include <iostream> #include <fstream> #include <iomanip> // 用于格式化输出 int main() { std::string path = "C:\\Users\\user\\Desktop\\Emp.bmp"; std::ifstream file(path, std::ios::binary); if (!file.is_open()) { std::cout << "ERROR"; return 1; } else { unsigned char fromfile[14]; // 用unsigned char避免符号扩展问题 file.read(reinterpret_cast<char*>(fromfile), 14); // 输出十六进制格式(两位对齐) std::cout << "十六进制输出:" << std::hex << std::setfill('0'); for (int i = 0; i < 14; ++i) { std::cout << std::setw(2) << static_cast<int>(fromfile[i]) << " "; } std::cout << "\n"; // 输出十进制格式 std::cout << "十进制输出:" << std::dec; for (int i = 0; i < 14; ++i) { std::cout << static_cast<int>(fromfile[i]) << " "; } std::cout << "\n"; file.close(); } return 0; }
3. 方式二:用结构体解析BITMAPFILEHEADER(更规范)
BMP文件头有标准结构体定义,直接读取到结构体里可以直接获取各个字段的数值,这是处理BMP文件的标准做法:
#include <iostream> #include <fstream> #include <cstdint> // 用固定宽度整数避免平台差异 // 定义BITMAPFILEHEADER结构体,取消字节对齐保证和文件结构一致 #pragma pack(push, 1) struct BITMAPFILEHEADER { uint16_t bfType; // BMP标识,固定为0x4D42(对应ASCII的'BM') uint32_t bfSize; // 文件总大小(字节) uint16_t bfReserved1; // 保留字段,固定为0 uint16_t bfReserved2; // 保留字段,固定为0 uint32_t bfOffBits; // 像素数据区相对于文件开头的偏移量(字节) }; #pragma pack(pop) int main() { std::string path = "C:\\Users\\user\\Desktop\\Emp.bmp"; std::ifstream file(path, std::ios::binary); if (!file.is_open()) { std::cout << "ERROR"; return 1; } BITMAPFILEHEADER bmpHeader; file.read(reinterpret_cast<char*>(&bmpHeader), sizeof(BITMAPFILEHEADER)); // 输出各个字段的数值 std::cout << "BMP标识: 0x" << std::hex << bmpHeader.bfType << "\n"; std::cout << "文件总大小: " << std::dec << bmpHeader.bfSize << " 字节\n"; std::cout << "像素数据偏移量: " << bmpHeader.bfOffBits << " 字节\n"; file.close(); return 0; }
说明:
#pragma pack(push,1)用于取消编译器的字节对齐优化,保证结构体的内存布局和BMP文件头的二进制结构完全匹配。- 使用
uint16_t、uint32_t这类固定宽度整数类型,避免不同平台上整数长度差异导致的解析错误。
内容的提问来源于stack exchange,提问作者Vladimir Pimenov
相关产品推荐
相关产品推荐

