【问题标题】:Any way to read big endian data with little endian program?有什么方法可以用小端程序读取大端数据?
【发布时间】:2010-01-07 18:02:49
【问题描述】:

一个外部小组为我提供了一个在 Big Endian 机器上编写的文件,他们还为文件格式提供了 C++ 解析器。

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

【问题讨论】:

  • 我会要求外部组支持可移植格式,例如 XML。
  • 或者至少提供一个没有损坏的解析器。如果他们的解析器只在大端机器上工作,那么他们的解析器就坏了。让他们修复它(或接受修复作为贡献)可能比让他们改变文件格式更现实。
  • 编译大端机器的代码并在你的小端机器上以qemu 运行:D

标签: c++ endianness


【解决方案1】:

早在铁器时代早期,古人在尝试将原始 PDP-11 小型计算机与其他原始计算机联网时遇到了这个问题。 PDP-11 是第一台 little-Endian 计算机,而当时大多数其他计算机都是 big-Endian。

为了解决这个问题,他们一劳永逸地开发了网络字节序概念(总是 big-Endia),以及相应的网络字节序宏 ntohs()、ntohl()、htons() 和 htonl() .使用这些宏编写的代码将始终“得到正确答案”。

依靠您的外部供应商在他们的代码中使用宏,他们提供给您的文件将始终是大端格式,即使他们切换到小端模式机器也是如此。重写他们提供给您的解析器以使用宏,即使您切换到大端机器,您也将始终能够读取他们的文件。

大量的程序员时间都浪费在了这个特定的问题上。有时候,我认为吊死做出 little-Endian 功能决定的 PDP-11 设计师是一个很好的论据。

【讨论】:

    【解决方案2】:

    尝试说服解析器团队包含以下代码:

    int getInt(char* bytes, int num) { 诠释; 断言(数字 == 4); ret = 字节[0]

    它可能比一般的 int i = *(reinterpret_cast<*int>(&myCharArray)); 更耗时,但在大端和小端系统上总是能得到正确的字节序。

    【讨论】:

    • 你的字节怎么只有 4 位? ;-)
    • 因为你在半睡半醒的时候写代码会发生这种情况
    【解决方案3】:

    一般来说,对此没有“简单”的解决方案。您将不得不修改解析器以交换从文件中读取的每个整数的字节。

    【讨论】:

      【解决方案4】:

      这取决于您对数据的处理方式。如果要打印数据,则需要交换所有数字上的字节。如果您在文件中查找一个或多个值,则对比较值进行字节交换可能会更快。

      总的来说,Greg 是正确的,但你必须努力做到这一点。

      【讨论】:

      • “如果您正在查看文件中的一个或多个值...”基本上意味着您将编写自己的解析器。如果不先交换文件的内容,则无法使用提供的解析器,因为您不知道它是否依赖于机器的字节序。
      • 在不了解所提供解析器的 API 的一些细节以及作为解析数据的预期用途的情况下,我提供的优化可能会适得其反。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        注意读入的数据类型。4 字节的intfloat 需要进行字节序校正。一个 4 字节的 ASCII 字符串不会。

        【讨论】:

        • 甚至可能无法包装它们的解析器 - 如果它检查幻数,那么当它们以错误的字节序加载时它将无法找到它们。存储在数据中的大小也会被误读。
        【解决方案7】:

        一般来说不会。

        如果读/写调用不知道类型(例如 fread 和 fwrite 不知道),那么它们就无法区分写入字节序敏感数据和字节序不敏感数据。

        根据解析器的结构,您可能能够避免一些麻烦,如果他们使用的 I/O 函数知道正在读取/写入的类型,那么您可以修改这些例程应用正确的字节序转换。

        如果您确实必须修改所有读/写调用,那么创建这样的例程将是一个明智的做法。

        【讨论】:

          【解决方案8】:

          您的问题以某种方式包含了答案:不!

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

          如果您在小端机器上读取(并想解释)大端数据,您必须以某种方式在某处转换数据。您可以在每次读取或读取整个文件后执行此操作(如果读取的数据不包含有关如何读取更多数据的任何信息) - 但无法省略转换。

          【讨论】:

            猜你喜欢
            • 2010-09-26
            • 1970-01-01
            • 2020-12-24
            • 1970-01-01
            • 2015-04-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多