You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

fread读取二进制文件后unsigned short缓冲区数据与原格式不符问题

二进制文件读取的字节序问题解析

兄弟,你猜的没错,这个问题完全是字节序(endianess)搞的鬼!咱们一步步拆解来看:

问题根源

你的二进制文件里的2字节数据是按大端字节序存储的:文件中第一个字节是0X(高字节),第二个字节是Y0(低字节),合起来就是你预期的0XY0十六进制值。

但你的系统大概率是小端字节序(绝大多数x86/x86_64架构的电脑都是小端),小端的规则是:内存中低地址存储数据的低字节,高地址存储高字节。当你用unsigned short(2字节类型)读取文件时,fread会把文件里的两个字节直接按内存顺序塞进unsigned short变量:

  • 文件第一个字节(0X)被存在unsigned short的低地址位(对应变量的低字节)
  • 文件第二个字节(Y0)被存在unsigned short的高地址位(对应变量的高字节)
    组合起来就变成了Y00X,和你预期的刚好反过来。

而用char数组读取没问题,是因为char是单字节类型,fread会严格按文件的字节顺序依次存入数组,不会做任何字节重组,所以完全符合文件里的0XY0顺序。

解决办法

这里给你两个靠谱的方案:

方案1:手动转换字节序

读取完unsigned short数组后,逐个把每个元素的高低字节交换,把小端转成大端:

for (int i = 0; i < bufferSize; i++) {
    buffer[i] = ((buffer[i] >> 8) | (buffer[i] << 8));
}

如果你的数据是符合网络字节序(大端)的,也可以用标准库的ntohs()函数(network to host short),效果一样:

#include <arpa/inet.h> // 注意引入头文件
for (int i = 0; i < bufferSize; i++) {
    buffer[i] = ntohs(buffer[i]);
}

方案2:用char数组读取后手动组装

继续用char数组读取,然后把两个字节手动组装成unsigned short,这样不管系统字节序是什么,都能得到正确的结果:

char buffer[bufferSize * 2];
// 这里省略fopen和fread的代码...
unsigned short result[bufferSize];
for (int i = 0; i < bufferSize; i++) {
    // 把高字节(buffer[2i])左移8位,再和低字节(buffer[2i+1])按位或
    result[i] = ((unsigned char)buffer[2*i] << 8) | (unsigned char)buffer[2*i+1];
}

这里要把char转成unsigned char再操作,避免符号位带来的问题。

内容的提问来源于stack exchange,提问作者Emanuele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:12:03