std::ofstream 在从 256 开始的字节边界上写入整数时出现奇怪的行为
std::ofstream weird behavior when writing integers on byte border from 256
试图创建二进制文件格式,但行为很奇怪。
std::ofstream outputFile;
outputFile.open (PATH, std::ios_base::out | std::ios_base::binary |
std::ios_base::app);
unsigned long long int timer3 = 255;
outputFile <<reinterpret_cast<const char *>(&timer3);
timer3 = 256;
outputFile <<reinterpret_cast<const char *>(&timer3);
timer3 = 257;
outputFile <<reinterpret_cast<const char *>(&timer3);
timer3 = 258;
outputFile <<reinterpret_cast<const char *>(&timer3);
二进制输出文件仅包含(十六进制)
FF 01 01 02 01
FF- 255
01 01- 257
02 01 -258
为什么它公然无视 256(和 512、1024..)?
将整数逐个整数写入二进制的最佳方法是什么?
使用流运算符 (<<
) 将 char*
写入文件时,它会在第一次终止 NULL (= 0) 时停止。
255 在 Little-Endian 中将被翻译成 0xff 0 0 0 因此它只写 0xff
256 将被翻译成 0 0x01 0,因此它被认为是一个空字符串,因为它从 0 开始。
257 将被翻译成 0x01 0x01 0,所以它会被打印出来。
任何第一个字节为 0 的数字(例如 512、768、1024 都是 256 的倍数)都不会用您的方法打印(在 Little Endian 机器上,例如 Windows 和 Linux) 因为第一个字节是 0.
通过使用格式化的插入运算符 <<
并给它一个 const char*
,你告诉流你给它一个 C 字符串,即一个空终止序列要解释为字符的字节。
但事实并非如此。
事实上,任何具有 "null" 组件(任何字节设置为零)的 long long
值都将终止该格式化插入。
<<
怎么知道什么时候停止?
您应该改用 outputFile.write(...)
,因为这是 "raw" 字节直接插入流的方式。
outputFile.write(reinterpret_cast<const char *>(&timer3), sizeof(timer3));
请注意,除非您在文件中写入一些指示符来告诉读者这些值是以 endianness 写入的,否则您将永远无法再次明确地读出它们。 (但是,对于一个简单的、不可移植的应用程序,这可能不是一个考虑因素。)
试图创建二进制文件格式,但行为很奇怪。
std::ofstream outputFile;
outputFile.open (PATH, std::ios_base::out | std::ios_base::binary |
std::ios_base::app);
unsigned long long int timer3 = 255;
outputFile <<reinterpret_cast<const char *>(&timer3);
timer3 = 256;
outputFile <<reinterpret_cast<const char *>(&timer3);
timer3 = 257;
outputFile <<reinterpret_cast<const char *>(&timer3);
timer3 = 258;
outputFile <<reinterpret_cast<const char *>(&timer3);
二进制输出文件仅包含(十六进制) FF 01 01 02 01
FF- 255
01 01- 257
02 01 -258
为什么它公然无视 256(和 512、1024..)?
将整数逐个整数写入二进制的最佳方法是什么?
使用流运算符 (<<
) 将 char*
写入文件时,它会在第一次终止 NULL (= 0) 时停止。
255 在 Little-Endian 中将被翻译成 0xff 0 0 0 因此它只写 0xff
256 将被翻译成 0 0x01 0,因此它被认为是一个空字符串,因为它从 0 开始。
257 将被翻译成 0x01 0x01 0,所以它会被打印出来。
任何第一个字节为 0 的数字(例如 512、768、1024 都是 256 的倍数)都不会用您的方法打印(在 Little Endian 机器上,例如 Windows 和 Linux) 因为第一个字节是 0.
通过使用格式化的插入运算符 <<
并给它一个 const char*
,你告诉流你给它一个 C 字符串,即一个空终止序列要解释为字符的字节。
但事实并非如此。
事实上,任何具有 "null" 组件(任何字节设置为零)的 long long
值都将终止该格式化插入。
<<
怎么知道什么时候停止?
您应该改用 outputFile.write(...)
,因为这是 "raw" 字节直接插入流的方式。
outputFile.write(reinterpret_cast<const char *>(&timer3), sizeof(timer3));
请注意,除非您在文件中写入一些指示符来告诉读者这些值是以 endianness 写入的,否则您将永远无法再次明确地读出它们。 (但是,对于一个简单的、不可移植的应用程序,这可能不是一个考虑因素。)