从二进制文件中读取后出现奇怪的数字
Strange number after reading from binary file
我想将十六进制32位数字写入二进制文件,然后使用repret_cast读取其中一些数字,并读取例如16位数字。我只读取16位,因为它决定了数据包的大小。代码中有一个示例。也许问题出在大端还是小端?
#include <iostream> // std::cout
#include <fstream> // std::ifstream
#include <cstdint>
#include <vector>
void saveTestData(void)
{
std::vector<std::uint_fast32_t> tab
{
0x50e5495c, 0xe7b50200, 0xbe6b2248, 0x08004510,
0x015c2340, 0x0000ff11, 0x1567c0a8, 0x004cc0a8,
0x003de290, 0xc35a0148, 0x00000000, 0x01200003,
0x00620000, 0x01140002, 0x00010000, 0x8000ef40,
0x22560003, 0xe0042150, 0x00006bbf, 0xd67c800f,
0x5b5b0003, 0xe0032150, 0x00006bbf, 0xd67c8007,
0x1b5d0003, 0xe0022150, 0x00006bbf, 0xd67c800a,
0xab5d0023, 0xe0052150, 0x00006bbf, 0xd67c8011,
0x8b5c6bbf, 0xd67c8c55, 0xaf896bbf, 0xd67c8c90,
0x4f896bbf, 0xd67c8cd4, 0xef8a6bbf, 0xd67c8d0d,
0x1f8a6bbf, 0xd67c8d43, 0x7f886bbf, 0xd67c8d8f,
0x8f896bbf, 0xd67c8dc4, 0xcf886bbf, 0xd67c8e19,
0x6f896bbf, 0xd67c8e4e, 0x1f8a6bbf, 0xd67c8e82,
0xcf8a6bbf, 0xd67c8ed7, 0x4f896bbf, 0xd67c8f0c,
0xef896bbf, 0xd67c8f4f, 0x8f896bbf, 0xd67c8f96,
0xef8a6bbf, 0xd67c8fdb, 0xcf896bbf, 0xd67c9008,
0xbf89000e, 0x80001006, 0xf0724646, 0xb45b0000,
0x00004646, 0xb45b0000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00004646, 0xb45b0000,
0x00004646, 0xb45b0000, 0x00008000, 0x00000001,
0x55550000, 0x0001aaaa, 0xaaaa0000, 0x01200003,
0x00620000, 0x01140002, 0x00010000, 0x8000ef40,
0x22560003, 0xe0042150, 0x0000
};
std::ofstream file;
file.open("test.omgwtf", std::ofstream::binary);
if(file.good())
{
file.write(reinterpret_cast<char*>(tab.data()), tab.size()*sizeof(std::uint_fast32_t));
file.close();
}
}
int main()
{
saveTestData();
std::ifstream file("test.omgwtf", std::ifstream::binary);
if(file.good())
{
file.seekg(0, file.end);
uint32_t length = file.tellg();
file.seekg(0, file.beg);
char *buffer = new char[length];
std::cout << "length = " << length << std::endl;
file.read(buffer, length);
std::uint_fast32_t *number32 = reinterpret_cast<std::uint_fast32_t*>(buffer);
std::cout << "1 number32 = " << *number32 << std::endl; // ok
number32 = reinterpret_cast<std::uint_fast32_t*>(buffer+4);
std::cout << "2 number32 = " << *number32 << std::endl; // ok
// read 0xbe6b (16 bits not 32)
// 0xbe6b (hex) = 48747 (dec)
std::uint_fast16_t *number16 = reinterpret_cast<std::uint_fast16_t*>(buffer+8);
std::cout << "3 number16 = " << *number16 << std::endl; // not ok!? why?
// read 2248 (16 bits not 32)
// 2248 (hex) = 8776 (dec)
number16 = reinterpret_cast<std::uint_fast16_t*>(buffer+10);
std::cout << "4 number16 = " << *number16 << std::endl; // not ok!? why?
file.close();
delete [] buffer;
}
return 0;
}
如何阅读数字16?1,2示例可以。3示例应该是48747而不是3194692168?4示例应该是8776而不是1158725227?
clear; g++ test2.cpp -std=c++11 -o test2; ./test2
std::binary
的名称不正确,它确实控制了换行符的转换。
iostream仅用于文本。您可以使用没有换行转换的文本(使用std::binary
,文件最终采用Unix换行约定,仅限n
)或具有换行转换的文字(不使用std::binary
,文件最终遵循OS约定,如n
、rn
,甚至r
)。
但是,即使使用std::binary
,EOF字符(ASCII 26)也可能被识别并结束输入。或者不是。标准没有说明。该标准没有为未翻译的文件访问提供任何机制。
人们一直在尝试设计一种更好的C++标准I/O机制,将文件访问与文本处理分离开来,但还没有人让每个人都满意。
对于二进制文件,请使用低级I/O机制。即使<stdio.h>
比iostreams更好(翻译更少),但它仍然有一些。特定于操作系统的函数,或者使用下面的操作系统函数的跨平台包装器(如boost::asio
)是二进制文件访问所需要的。
此外,到处都有严格的混叠冲突。不要像那样使用reinterpret_cast
,而是使用memcpy
或从输入文件中单独读取正确大小的块。
最后,您读取了错误的大小变量。uint_fast16_t
不是16位,它是16位或更多,无论是最快的。几乎可以肯定的是,32位在您的CPU上比16位更快。如果您想要16位,请使用uint16_t
。如果您想要尽可能接近(但不是更少),请使用uint_least16_t
。CCD_ 16类型家族适用于循环计数器等局部变量。由于大小未知,它们对I/O毫无用处。
一旦你弄清楚了这一切,你就需要担心原始数据的端序性,因为它是以32位(或更多)值的序列写入的,无论高半部分还是低半部分首先写入文件都取决于平台。
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- C++单个生成文件多个二进制文件
- 尝试将数字写入二进制文件时引发异常
- 快速读取带有数字 c++ 的二进制文件时出现问题
- 从二进制文件读取到数组:前面的任意数字
- 从二进制文件中读取后出现奇怪的数字
- C++读取二进制文件,其中包含类型为double的数字