我有一个已知格式的二进制文件。例如,让format像这样:
该文件应如下所示(为可读性添加了空格):
5 hello 3 0.0 0.1 0.2 -0.3 -0.4 -0.5
这里5-是2个字节:0x05 0x00。 “hello”-5个字节,依此类推。
现在,我想阅读该文件。目前,我正在这样做:
char buffer[2]
unsigned short len{ *((unsigned short*)buffer) };
。现在我有一个字符串的长度。 vector<char>
的流,并从此 vector 创建std::string
。现在我有了字符串ID。 char bufferFloat[4]
并为每个 float 都转换*((float*)bufferFloat)
。 这行得通,但对我来说,看起来很难看。我可以直接阅读
unsigned short
或float
或string
等,而无需创建char [x]
吗?如果没有,正确转换的方式是什么(我读到我正在使用的样式-是旧样式)?附注:当我写一个问题时,我脑海中出现了更清晰的解释-如何从
char [x]
中的任意位置转换任意数量的字节?更新:我忘了明确提到字符串和浮点数据长度在编译时未知,并且是可变的。
最佳答案
在C++中可以正常工作的C方法是声明一个struct:
#pragma pack(1)
struct contents {
// data members;
};
注意
然后将读取缓冲区直接转换为struct类型:
std::vector<char> buf(sizeof(contents));
file.read(buf.data(), buf.size());
contents *stuff = reinterpret_cast<contents *>(buf.data());
现在,如果您的数据大小是可变的,则可以分成几个块。要从缓冲区读取单个二进制对象,可以使用reader函数:
template<typename T>
const char *read_object(const char *buffer, T& target) {
target = *reinterpret_cast<const T*>(buffer);
return buffer + sizeof(T);
}
主要优点是这样的阅读器可以专门用于更高级的c++对象:
template<typename CT>
const char *read_object(const char *buffer, std::vector<CT>& target) {
size_t size = target.size();
CT const *buf_start = reinterpret_cast<const CT*>(buffer);
std::copy(buf_start, buf_start + size, target.begin());
return buffer + size * sizeof(CT);
}
现在在您的主解析器中:
int n_floats;
iter = read_object(iter, n_floats);
std::vector<float> my_floats(n_floats);
iter = read_object(iter, my_floats);
注意:正如Tony D观察到的那样,即使您可以通过
#pragma
指令和手动填充(如果需要)正确地进行对齐,也可能会遇到(最佳情况下)性能问题或(最坏的情况)捕获信号。仅当您可以控制文件格式时,此方法才可能很有趣。关于c++ - 解析二进制文件。什么是现代方式?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26845538/