使用 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这个结构进行外部数据交换的目的。
我正在寻找如何解析长二进制数据的想法,例如:“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 tovector<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这个结构进行外部数据交换的目的。