我目前正在处理某些任意值的二进制文件格式,包括一些字符串和字符串长度值,这些值存储为uint32_t
。
但我想知道,如果我将fwrite
的字符串长度写入little-endian系统上的文件,并在big-endian系统上使用fread
从同一文件中读取该值,字节的oder会被反转吗?如果是这样,解决这个问题的最佳做法是什么?
编辑:肯定有一些GNU功能可以为我做这个,并且使用,测试和验证,比如,20年?
答案 0 :(得分:3)
是的,它会,因为fread()
对 war 原始字节进行操作。如果内存中的字节顺序不同,那么文件中的字节顺序也不同。
如果是这样,解决这个问题的最佳做法是什么?
检测系统的字节顺序,如果字节与文件格式的字节顺序不匹配,则翻转字节。
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);
}
答案 1 :(得分:2)
如果我使用fwrite将字符串长度写入little-endian系统上的文件,并在big-endian系统上使用fread从同一文件中读取该值,那么字节的oder会被反转吗?
是。 fwrite
只是以线性顺序将内存内容写入文件。 fread
只是按线性顺序从文件读取到内存。
解决这个问题的最佳做法是什么?
决定您的文件订购。然后编写包装函数来向文件写入和从文件读取整数。在此函数内部,如果您在具有相反排序的系统上,则有条件地翻转字节顺序。
(关于确定系统的字节顺序有lots of questions here。)
肯定有一些GNU功能可以为我做这个
标准库中没有任何内容。但是,POSIX为此定义了一系列函数:ntohl
, htonl
, etc.。它们通常用于网络传输,但同样可用于文件。
答案 2 :(得分:2)
是的,整数上的fwrite
和fread
会使您的文件格式无法移植到另一个字节序,因为其他答案正确陈述。
在最佳实践中,我将阻止任何条件字节翻转和字节顺序测试。确定文件格式的字节顺序,而不是写入和读取字节,并通过ORing和移位从中生成整数。
换句话说,问题I agree with Rob Pike。
答案 3 :(得分:1)
Linux提供
htobe16,htole16,be16toh,le16toh,htobe32,htole32,be32toh,le32toh,htobe64,htole64,be64toh,le64toh - 在主机和大/小端字节顺序之间转换值