1

假设我有一个二进制文件;它包含正二进制数,但用大端写成 32 位整数

我如何阅读这个文件?我现在有这个。

int main() {
    FILE * fp;
    char buffer[4];
    int num = 0;
    fp=fopen("file.bin","rb");
    while ( fread(&buffer, 1, 4,fp) != 0) {

        // I think buffer should be 32 bit integer I read,
        // how can I let num equal to 32 bit big endian integer?
    }
    return 0;
}
4

3 回答 3

8

将缓冲区声明为:

unsigned char buffer[4];

您可以使用它来转换字节顺序:

int num = (int)buffer[0] | (int)buffer[1]<<8 | (int)buffer[2]<<16 | (int)buffer[3]<<24;

顺便提一句

当然,这适用于小端的 x86 架构 - 否则您的平台字节序可能与文件的字节序匹配,因此不需要转换。这样你就可以直接读入你的 int 而无需转换。

于 2013-11-03T08:33:24.563 回答
4

你需要先找出你的字节序:

如何使用 C 以编程方式找到我的 PC 的字节序?

然后你需要采取相应的行动。如果您与文件相同,则可以按原样读取值,如果您处于不同的字节序,则需要重新排序字节:

union Num 
{
    char buffer[4];
    int num;
} num ;

void swapChars(char* pChar1, char* pChar2)
{
    char temp = *pChar1;
    *pChar1 = *pChar2;
    *pChar2 = temp;
}

int swapOrder(Num num)
{
    swapChar( &num.buffer[0], &num.buffer[3]);
    swapChar( &num.buffer[1], &num.buffer[2]);

    return num.num; 
}

while ( fread(&num.buffer, 1, 4,fp) != 0)
{
    int convertedNum;
    if (1 == amIBigEndian) 
    {
        convertedNum = num.num
    } 
    else
    {
        convertedNum = swapOrder(num);
    }
    // Do what ever you want with convertedNum here...
}
于 2013-11-03T09:13:41.137 回答
3

它是特定于操作系统和处理器架构的。

您可能会使用htonl(3)等例程ntohl...

但是您确实应该以定义明确的格式进行序列化。

在当前的机器上(I/O 非常慢,wrt CPU 速度)我赞成使用文本序列化格式,如JSONYAML,......但你也可以使用二进制序列化(和库),如BSONXDRASN.1s11n库....

如果可能,请改进生产者代码(编写文件的file.bin代码)和相应的消费者代码。

二进制数据本质上是脆弱的,因为它是特定于系统和架构的。至少,将其格式记录得非常好,并最好提供一些工具来将其从文本格式转换为文本格式。

有几个用于 C++ 的 JSON 库,如jsoncpprapidjson以及用于 C 的jansson等......

于 2013-11-03T08:32:37.010 回答