如何在小端程序中读取大端数据?

5

一个外部团队提供给我一个在Big Endian机器上编写的文件,他们还提供了一个用于该文件格式的C++解析器。

我只能在一个Little Endian机器上运行这个解析器 - 有没有办法在使用他们的解析器时不需要在每次读取后添加swapbytes()调用来读取文件?


3
我会敦促外部团体支持可移植格式(如XML)。 - anon
3
或者提供一个没有问题的解析器。 如果他们的解析器只在大端机器上工作,则他们的解析器有问题。 催促他们修复它(或接受修复作为贡献)可能更现实,而不是催促他们更改文件格式。 - Steve Jessop
1
为大端机器编译代码,并在您的小端机器上使用 qemu 运行它 :D - ephemient
8个回答

14
在早期的铁器时代,古人们在试图将原始的PDP-11小型计算机与其他原始计算机网络化时遇到了这个问题。PDP-11是第一台小端字节序(little-Endian)的计算机,而当时大多数其他计算机都采用大端字节序(big-Endian)。
为了彻底解决这个问题,他们开发出了网络字节序概念(总是采用大端字节序),以及相应的网络字节序宏ntohs()、ntohl()、htons()和htonl()。使用这些宏编写的代码将始终“得到正确的答案”。
依靠外部供应商在其代码中使用这些宏,他们提供给您的文件将始终是大端字节序,即使他们切换到小端字节序的计算机上也是如此。重写他们给您的解析器以使用这些宏,即使您切换到大端字节序的计算机上,您也将始终能够读取他们的文件。
这个特定问题浪费了大量程序员的时间。有时我认为可以提出一个好的理由来谴责设计小端字节序的PDP-11设计师。

4
尝试说服解析器团队包含以下代码:
int getInt(char* bytes, int num)
{
    int ret;
    assert(num == 4);
    ret = bytes[0] << 24;
    ret |= bytes[1] << 16;
    ret |= bytes[2] << 8;
    ret |= bytes[3];
    return ret;
}
这可能比一般的int i = *(reinterpret_cast<*int>(&myCharArray));更耗时,但在大端和小端系统上始终正确。

2
你的字节为什么只有4位呢?;-) - Steve Jessop
2
因为当你半睡半醒时编写代码就会发生这种情况。 - doron

2

一般来说,这个问题没有“简单”的解决方案。您需要修改解析器,交换从文件中读取的每个整数的字节。


2

这取决于您对数据要进行什么操作。如果您要打印数据,则需要交换所有数字的字节顺序。如果您正在查找文件中的一个或多个值,则通过交换字节顺序可以更快地比较值。

总的来说,Greg是正确的,您必须以较为困难的方式完成此任务。


如果你正在查找文件中的一个或多个值...这基本上意味着你将编写自己的解析器。在不知道解析器是否依赖于机器的字节序之前,你不能使用提供的解析器而不进行文件内容交换。 - groovingandi
不了解所提供解析器的API的一些细节,也不了解解析数据的预期用途,我提供的优化可能会产生反效果。 - Thomas Jones-Low

2

最好的方法是在文件格式中定义字节顺序,而不是说它取决于机器。 无论CPU运行在哪个机器上,编写者都必须按正确的顺序编写字节,读者也必须这样做。


0

如果您不想修改他们的解析器,您可以编写一个包装器来包装他们的解析器并反转字节。

请注意读入数据的类型。4字节的intfloat需要进行大小端校正。4字节ASCII字符串则不需要。


甚至可能无法包装它们的解析器 - 如果它检查魔数,那么当它们以错误的字节序加载时,它将无法找到它们。存储在数据中的大小也会被错误读取。 - Steve Jessop

0

一般而言,不能。

如果读/写调用不是类型感知的(例如fread和fwrite),那么它们无法区分写入大小端敏感数据和大小端不敏感数据。

根据解析器的结构,您可能可以避免某些痛苦,如果它们使用的I/O函数知道正在读取/写入的类型,则可以修改这些例程并应用正确的字节顺序转换。

如果确实必须修改所有读/写调用,则创建此类例程将是明智的选择。


0

你的问题有点包含了答案:不行!

我只能在小端机器上运行解析器 - 有没有办法在不添加swapbytes()调用的情况下使用他们的解析器读取文件?

如果你在小端机器上读取(并想要解释)大端数据,你必须在某个地方进行数据转换。你可以在每次读取后或者整个文件读取完毕后进行转换(如果读取的数据不包含如何读取进一步数据的信息) - 但是没有办法省略转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接