2

我目前正在研究一些任意值的二进制文件格式,包括一些字符串和字符串长度值,它们存储为uint32_t's.

但我想知道,如果我将字符串长度写入fwrite小端系统上的文件,并在大端系统上从同一个文件中读取该值,fread字节的顺序会反转吗?如果是这样,解决这个问题的最佳做法是什么?

编辑:肯定有一些 GNU 功能可以为我做这件事,并且已经使用、测试和验证了 20 年?

4

4 回答 4

3

是的,fwrite并且fread在整数上使您的文件格式无法移植到另一个字节序,正如其他答案正确说明的那样。

作为最佳实践,我完全不鼓励任何有条件的字节翻转和字节序测试。确定文件格式的字节顺序,而不是写入和读取字节,并通过 ORing 和移位从它们中生成整数。

换句话说,我同意 Rob Pike在这个问题上的看法。

于 2013-02-09T21:00:49.060 回答
3

如果我使用 fwrite 将字符串长度写入 little-endian 系统上的文件,并在 big-endian 系统上使用 fread 从同一个文件中读取该值,字节的顺序是否会反转?

是的。 fwrite简单地将内存内容以线性顺序写入文件。 fread只是以线性顺序从文件读取到内存。

解决这个问题的最佳做法是什么?

决定您的文件的顺序。然后编写包装函数来向/从文件中写入和读取整数。在此函数中,如果您在具有相反顺序的系统上,则有条件地翻转字节顺序。

(这里有很多关于确定系统字节序的问题。)

当然必须有一些 GNU 功能来为我做这件事

标准库中什么都没有。但是,POSIX 为此定义了一堆函数:ntohlhtonl。它们通常用于网络传输,但同样可以用于文件。

于 2013-02-09T20:41:33.437 回答
3

是的,它会,因为fread()战争原始字节进行操作。如果内存中的字节顺序不同,文件中的字节顺序也会不同。

如果是这样,解决这个问题的最佳做法是什么?

检测系统的字节序,如果它与文件格式的字节序不匹配,则翻转字节。

int is_little_endian()
{
    uint32_t magic = 0x00000001;
    uint8_t black_magic = *(uint8_t *)&magic;
    return black_magic;
}

uint32_t to_little_endian(uint32_t dword)
{
    if (is_little_endian()) return dword;

    return (((dword >>  0) & 0xff) << 24)
         | (((dword >>  8) & 0xff) << 16)
         | (((dword >> 16) & 0xff) <<  8)
         | (((dword >> 24) & 0xff) <<  0);
}
于 2013-02-09T20:42:51.517 回答
1

Linux 提供

htobe16, htole16, be16toh, le16toh, htobe32, htole32, be32toh, le32toh, htobe64, htole64, be64toh, le64toh - 在主机和大/小端字节顺序之间转换值

[ https://linux.die.net/man/3/le32toh]

于 2017-10-12T15:27:04.983 回答