使用 C++ 解析长字符串二进制数据

Parsing long strings of binary data with C++

我正在寻找如何解析长二进制数据的想法,例如:“10100011111000111001” 位:0-4 是 id 位 5-15 是数据 等等等等...

二进制数据结构可以更改,所以我需要构建一种数据库来存储如何解析每个字符串的数据。

插图(可能是 200~ 位):

想法如何实现呢? 谢谢

编辑

我在这里错过了什么?

struct Bitfield {
uint16_t  a : 10 , b:6;};


void diag(){
uint16_t t= 61455;
struct Bitfield test = {t};

cout<<"a: "<<test.a<<endl;
cout<<"b: "<<test.b<<endl;

return;}

输出为:

a: 15
b: 0

“最佳方法”取决于问题的细节。

如果整数符合可用的最大整数类型(通常是 long long),则首先将字符串转换为整数(例如使用 stoi/stol/stoll 函数,假设 C++11 可用)。然后使用位移结合二进制和(&)来提取您感兴趣的值的部分。

如果整数不适合可用的最大整数类型,将其拆分为字符串(使用 substr 函数),然后将子字符串一个一个地转换为整数。

可用选项

要管理大量结构化位,您有以下选择:

  • C++ bit-fields:你定义了一个带有位域成员的结构。您可以拥有任意数量的成员,前提是每个成员的位数不超过 unsigned long long.
    它超级容易使用;编译器为您管理对位或位组的访问。主要的不便之处在于位布局是依赖于实现的。因此,这不是编写以二进制格式交换数据的可移植代码的选项。

  • 无符号整数类型的容器:你定义一个足够大的数组来容纳所有的位,并使用以下组合访问位或位组逻辑运算。 它需要轻松地进行二进制运算,并且如果将位组拆分为连续元素则不切实际。为了以可移植的方式与外界交换二进制格式的数据,您需要处理大端和小端架构之间的差异,或者使用 uint8_t.

    的数组
  • std::vector<bool>:让您完全灵活地管理位。主要限制是您需要分别处理每一位。此外,没有 data() 成员可以直接访问二进制数据。

  • std::bitset: is very similar to vector<bool> for accessing bits. It has a fixed size at compile time, but offers useful features such as reading and writing binary in ascci from strings or streams]5,整型二进制值转换,全bitset逻辑运算

  • 这些技术的组合

做出你的选择

要以可移植的方式与外界通信,最简单的方法是使用位集。 Bitsets 以使用 ascci '0' 或 '1'(或其任何替代品)

的格式提供简单的 input/output/string 转换
bitset<msg_header_size> bh,bh2;
bitset<msg_body_size> bb,bb2;
cin>>bh>>bb;  // reads a string od ascii 0 and 1 
cout<<bh<<"-"<<bb<<endl<<endl;  // writes a string of ascii 0 and 1

您还可以转换 from/to 二进制数据(但是是单个元素,对于 bitset 大小足够大):

bitset<8> b(static_cast<uint8_t>(c));
cout<<b<<endl; 
cout<<b.to_ulong()<<endl;  

对于 reading/writing 大集合,您需要读取小位集并使用逻辑运算符将它们聚合到更大的位集中。这看起来很耗时,实际上它非常接近你在积分容器中所做的事情,但不必关心字节边界。

在你的情况下,使用固定大小 header 和最大大小,bitset 似乎是交换二进制文件的不错选择(但是要小心,因为变量部分是右对齐的)与外部世界的数据。

对于处理数据内容,访问特定位很容易,但是您必须使用一些逻辑操作(移位和)来访问位组。而且,如果你想要可读和可维护的代码,最好将位布局抽象化。

结论:

因此,我强烈建议使用内部一个bit-field结构来处理数据,并保持与原始数据相当的内存占用 and的同时,使用bitsets只是为了from/to这个结构进行外部数据交换的目的。