最近因工作要求,需要使用erlang编程语言进行程序开发,不过一直没
有机会应用erlang的二进制使用,个人感觉erlang的二进制功能很强大,
但是里面有些知识点比较拗口,一不小心就模糊了相关的使用规则,下
面列出其使用方式以备忘记:
1.将一个整数强制拆分成指定长度的二进制表示:
1>Bin = <<17:15>>.
<<0,17:7>>
本来将整数:17用二进制表示,一个8bit的方式即可完整表示出来,现
在强制要求用15bit来表示,则高位补0,低位是 7bits的比特流即可。
2. <<D:8,E:1/binary>> = <<59704:16>>.
D:233
E:<<"8">>
其中D是以10进制表示,所以返回为233,E以2进制表示,所以返回为
二进制格式。
3. bitstring的用法:
1> <<A:8/bitstring,B:8>> = <<59704:16>>.
<<"é8">>
2> A.
<<"é">>
3> B.
56
通过上面的效果可以知道,在进行二进制匹配时,如果绑定变量的
Type不同,返回的类型也是不同的。
4.二进制的Type类型: integer、bits、bitstring:这3种类型默认1单位所占
bit位为1位,可以通过设置unit:N来更改默认设置, 例如:<<A:8/unit:2>> = <<17:16>>
至于float类型,测试时总报异常,一时没找到原因,此处不列出来。
binary、bytes:这两类默认占用bit位为8位,同上,可以通过设置unit的值更改默认值。
Unit:可以通过此属性设置每单位占用的bit位数,该值允许的范围为
1~255。
Size:进行比特位匹配时使用格式类似:<<Vale:Size/TypeList>>,其中
Size代表占用多少个单位的Unit,其中每个Unit单位默认所占bit位在上面
有说明,那么当前Value总共所占bit位数目为: Size * Unit。
endian属性:可选值为big | little | native,当值为big时,按照2进制数据从左到右的正常次序每隔
1> 2#011000001110100110011010. [01100000,11101001,10011010]
6351258
2> <<A:20,B:3>> = <<6351258:23>>.
<<193,211,26:7>>
3> A.
793907
4> B.
2
5> 2#11000001110100110011. [11000001,11010011,0011]
793097
6> <<C:20,D:3>> = <<6351258:23/little>>.
<<154,233,96:7>>
8> C.
634524
9> D.
0
10> 2#10011010111010011100. [10011010,11101001,1100]
634524
11> 2#011000001110100110011010. [01100000,11101001,10011010]
6351258
12> <<E:3,F:20>> = <<6351258:23/little>>.
<<154,233,96:7>>
13> E.
4
14> F.
881888
15> 2#100
4
16> 2#11010111010011100000. [11010,11101001,1100000]
881888
这个测试会让人比较迷惑,不过通过观察数据可以得到规律:
二进制数据流总是倾向于以8比特为一个组合;
二进制数据流中,每一个8比特位的单组中,从左往右,左侧总是高位,右侧总是低位,无论上面的endian类型为big或者little;
当将一个整数转换为一个非对齐的bit流(例如上面将本应设置为24bit位的整数6351258,强制设置为23bit)时,可以根据如下的模型设想其砍掉多余的bit位的情况,我们先看实例:
1> <<6351258:23/little>>.
<<154,233,96:7>>
2> 2#011000001110100110011010. [01100000,11101001,10011010]
6351258
3> 2#10011010.
154
4> 2#11101001.
233
5> 2#01100000.
96
6> <<6351258:23/big>>.
<<193,211,26:7>>
7> 2#11000001.
193
8> 2#11010011.
211
9> 2#00011010.
26
总结:上面的测试给我们这样的推断:
无论endian类型为big模式或者little模式,可以先按照big模式取得整数的
二进制流,该二进制流是对齐的模式,也就是二进制流长度为8的倍数,然后砍掉二进制流最左侧的多出来的bit位(记住:无论是big模式还是little模式),获取最新的bit流信息。
接下来,当为big模式时,在新big流的基础上,从左往右,每8位bit数据作为一组,当最后的bit流长度不足8位时,为其在左侧高位补0;并且这产生的多个bit组合中,越往左侧的越是高位,最后一个bit组是最低位;
当为little模式时,需要从右往左进行分组,每8bit位数据位一组,最右侧的组合是高位,中间的是次高位,最左侧的是最低位。
经过上面的分析后,我们现在可以接着看最上面的二进制匹配情况,当endian模式为big模式时,变量A将匹配二进制数据流的最高位数据,其提取20个bit位,这解释了为什么变量A绑定整数:634524;B变量绑定整数:2。
当endian模式为little模式时,变量C一样匹配二进制数据流的最高位数据,最高位数据流按照bit组来组合,却是从big模式下的最右侧开始组合:首先最右侧的8位作为最高位,然后是中间的8位作为次高位,组后是最左侧7bit中的高4位:1100,这解释了为什么变量C的值为634524而D变量的值为0,如果还不确定这种理解是否正确,还可以参考后面变量E和F的匹配情况。
5.二进制数据流的匹配方式:
1> 2#11010011.
211
2> <<2#1101:4,X:4>> = <<211>>.
<<"Ó">>
3> X.
3
至于二进制中的sign属性,目前还没有进行测试,有兴趣的朋友可以将测试结果分享一下。