首页 文章

从C文件读取文件时,切换字节序的最快方法是什么?

提问于
浏览
-2

我已经提供了一个二进制文件来读取,它包含一系列原始值 . 为简单起见,假设它们是无符号整数值,长度为4字节或8字节 . 对我来说不幸的是,这些值的字节顺序与我的处理器的字节顺序不相容(很少与大,反之亦然;从不介意奇怪的PDF-endianness等);我希望这些数据在内存中具有正确的字节顺序 .

考虑到我正在从文件中读取数据这一事实,最快的方法是什么?如果不值得利用这个事实,请解释原因 .

2 回答

  • 2

    考虑到您正在从文件中读取数据这一事实,与文件IO相比,切换字节序的方式对运行时的影响不大 .

    可能会产生重大影响的是您如何阅读数据 . 试图不按顺序读取字节不是一个好主意 . 只需按顺序读取字节,然后切换字节顺序 . 这将读取和字节交换分开 .

    我通常希望从字节交换代码,当然在读取文件的情况下,它适用于任何字节序,并且不依赖于架构特定的指令 .

    char* buf = read(); // let buf be a pointer to the read buffer
    uint32_t v;
    
    // little to native
    v = 0;
    for(unsigned i = 0; i < sizeof v; i++)
        v |= buf[i] << CHAR_BIT * i;
    
    // big to native
    v = 0;
    for(unsigned i = 0; i < sizeof v; i++)
        v |= buf[i] << CHAR_BIT * (sizeof v - i);
    

    这适用于本机是大型,小型还是中等端种类之一 .

    当然,boost已经为您实现了这些,因此无需重新实现 . 此外,POSIX和windows C库都提供了ntoh?系列函数,可用于将大端转换为/从本机转换 .

  • 1

    不是最快的,但可移植的方法是将文件读入(unsigned)int数组,将int数组别名为char(允许每个严格的别名规则)并在内存中交换字节 .

    完全便携的方式:

    swapints(unsigned int *arr, size_t l) {
        unsigned int cur;
        char *ix;
        for (size_t i=0; i<l; i++) {
            int cur;
            char *dest = static_cast<char *>(&cur) + sizeof(int);
            char *src = static_cast<char *>(&(arr[i]));
            for(int j=0; j<sizeof(int); j++) *(--dest) = *(src++);
            arr[i] = cur;
        }
    }
    

    但如果您不需要可移植性,某些系统会提供交换功能 . 例如,BSD系统有 bswap16bswap32bswap64 分别在 uint16_tuint32_tuint_64_t 中交换字节 . 毫无疑问,Microsoft或GNU-Linux世界中存在等效函数 .

    或者,如果您知道该文件是网络顺序(大端)而您的处理器不是,则可以分别使用 ntohsntohl 函数 uint16_tuint32_t .

    备注(根据AndrewHenle的评论):无论主机端是什么,始终可以使用 ntohsntohl - 只是它们在大端系统上是无操作的

相关问题