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

时间:2016-06-14 11:13:12

标签: c++ performance file endianness

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

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

2 个答案:

答案 0 :(得分:2)

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

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

通常需要字节交换代码,当然,在读取文件的情况下,它适用于任何字节序,并且不依赖于特定于架构的指令。< / p>

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 :(得分:1)

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

完全便携的方式:

bswap16

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

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

备注(根据AndrewHenle的评论):无论主持人的字节顺序如何,ntohl.spec总是可以使用 - 只是它们在大端系统上是无操作的