zoukankan      html  css  js  c++  java
  • Erlang第二课 ---- bit串

    Erlang是被设计来用在电信设备中的,这意味着需要处理大量的二进制数据。也正因为如此,Erlang把binary和binary string提升到了一个相当高的位置,提供了极为丰富的操作机制。当然,丰富意味着多,多了可能会有些眼花缭乱,有人给的建议是,如果感觉搞不定怎么处理bit串,可以先在shell里面慢慢的试出自己要的表达,然后copy到程序中去。

    1、下面例子形象展示了bit 流的组装:

    > Color = 16#F09A29.
    15768105
    > Pixel1 = <<Color>>.                          
    <<")">>
    > Pixel2 = <<Color:16>>.
    <<154,41>>
    > Pixel3 = <<Color:24>>.
    <<240,154,41>>

    我们可以看到:

    1)在定义Pixel1时,我们没有给bit串指定长度,所以,它默认是一个byte,而0x29恰好是字符“)”;

    2)在定义Pixel2时,我们指定bit串的长度是16,我们看到他把后面16位转换为bit串,即我们看到的两个8bit长数字;

    3)在定义Pixel3时,我们指定bit串的长度是24,然后我们就得到了完整的bit串-3个8bit长的bit串。

    2、用patten matching 对bit流进行拆分,具体如下:

    1> Pixels = <<213,45,132,4,76,32,76,0,0,234,32,15>>.
    <<213,45,132,4,76,32,76,0,0,234,32,15>>
    2> <<Pix1,Pix2,Pix3,Pix4>> = Pixels.
    ** exception error: no match of right hand side value <<213,45,132,4,76,32,76,0,0,234,32,15>>
    3> <<Pix1:24,Pix2:24,Pix3:24,Pix4:24>> = Pixels.
    <<213,45,132,4,76,32,76,0,0,234,32,15>>
    4> <<Pix1:24>>.
    <<213,45,132>>

    这里的操作有:

    1)表达式2并没有指定patten matching的长度,Erlang默认按8bit处理,所以,4x8=32bit,与右边的4x24长度不匹配。即,弹出的error:no match。

    2)表达式3我们指定了24-24-24-24这样的长度,与右边匹配,所以取出了<<Pix1:24>>=<<213,45,132>>.

    另外,如果我们只去第一个8位,是没必要去拆开整个bit串的,Erlang给我们准备了一个语法糖:

    > <<R:8,Rest/binary>> = Pixels.
    <<213,45,132,4,76,32,76,0,0,234,32,15>>
    > R.
    213

    3、Erlang中bit串的描述方式包括:

    • Value
    • Value:Size
    • Value/TypeSpecifierList
    • Value:Size/TypeSpecifierList

    我们来具体看看这些是什么。其中,TypeSpecifierList有“Unit:xxx”, “Type”,“Signedness”还有“Endianness”几种,使用时用(-)来隔开:

    -Value. 这个bit串代表的这个数值为多少。

    -Size. 这一bit串占用了多少Unit。

    -Unit:xxx. xxx 取值范围是1-255,表示每Unit占的bit数。Size x Unit为该数实际占用的bit数。

    -Type. 这个属性描述了bit流是按什么方式组织的,有integer,float,binary(bytes),bitstring(bits),utf8,utf16, and utf32。如果没有指定格式,Erlang会默认认为他是integer类型。其中integer,float,binary默认的一个unit占1bit,我们可以用Unit来指定各个type每个unit占用几个bit;这仅仅表示它申请了这么多内存,但是存放时仅仅是在前面插了一些0。例如,

    > <<8:8/unit:2>> == <<8:16>>.
    true
    > <<123456:16/unit:2>>.
    <<0,1,226,64>>
    > <<123456:32>>.
    <<0,1,226,64>>

    如上,“16个unit,每个unit占2bit”与“32个unit,每个unit占1bit”表示的是同样多的bit数。

    -Signedness.这一属性只有两个选项signed和unsigned,默认是unsigned。同时,只有bit串是integer类型的时候,我们才会考虑这一属性。

    -Endianness.可能的值有big,little,native,默认是big,而且在标准的网络协议应用中都是big ending。同时,大小端只有在数据是integer,utf16,utf32,或者是float时有用。native取决于cpu运行时使用大端还是小端。

     举例:

    1> <<Y:4/unit:8>> = <<72,0,0,0>>.
    <<72,0,0,0>>
    2> Y.
    1207959552
    3> <<X:4/little-unit:8>> = <<72,0,0,0>>.
    <<72,0,0,0>>
    4> X.
    72

    上面的代码中:

    -1中,这个bit串是integer型的,它的值为Y,Size为4,每个Unit为8位。那么,右边的bit串代表一个integer的话,这个integer的值应该是1207959552。

    -3中,这个bit串同样是integer型的,它的值为X,Size为4,每个Unit为8位;但是,这个bit串是小端存放的。那么,右边的bit串如果代表一个小端存放的integer的话,这个integer的值应该是72。

    4、bit串的运算方式有:左移(bsl,bit shift left),右移(bsr,bit shift right),按位与(band),按位或(bor),按位亦或(bxor),按位取反(bnot)。

    5、binary strings处理字符串要比Lists更加的节省空间,主要是Lists事实上更像是链表,而binary更像是array(a tightly packed block of memory)。所以,在不需要对字符串进行太多处理,或者是内存比较敏感的情况下,大家更乐意用binary string。

    ps:尽管binary string是种轻量级的方案,但是,我们还是应该尽量避免使用它来做tag。这是因为,没有什么比atom更适合做tag了,使用其它就多余了。

    > <<"this is a binary string!">>.
    <<"this is a binary string!">>

    6、binary comprehension是和Lists comprehension一样的存在。只不过,我们在描述元素属于某个bit串时,使用的符号由"<-"变成了“<=”;描述的目标是一个bit串时,我们要把最外面的“[ ]”,同样换成"<<>>"。具体可以看下面两个例子:

    > Pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>>.
    <<213,45,132,64,76,32,76,0,0,234,32,15>>
    > RGB = [ {R,G,B}||<<R:8,G:8,B:8>> <= Pixels ].
    [{213,45,132},{64,76,32},{76,0,0},{234,32,15}]

    这样,我们轻松的把Pixels数据转化为RGB tuple的lists。注意“<<R:8,G:8,B:8>> <= Pixels”一句,8-8-8只有24个bit,而Pixels有12 X 8个bit,所以,这里处理的时候,是按描述循环取了四次。

    另一个例子恰恰相反:

    > << <<R:8,G:8,B:8>> || {R,G,B} <- RGB >>.
    <<213,45,132,64,76,32,76,0,0,234,32,15>>

     ps:我们要注意generator返回的bit串是什么类型,忽略的话可能会出错。比如在下面例子中:

    > << <<Bin>> || Bin <- [<<3,7,5,4,7>>]>>.
    ** exception error: bad argument
    > << <<Bin/binary>> || Bin <- [<<3,7,5,4,7>>]>>.
    <<3,7,5,4,7>>

    首先应该注意到,[<<3,7,5,4,7>>]是构建了一lists,其中只有一个元素,即,一个bit串。

    上面的代码先是定义bit串<<Bin>>,Value的类型默认是integer,即Bin是一个integer类型的数,然后尝试把generator产生的bit串赋值给Bin...等等,这就是bad argument的根源所在。

    第二次,我们声明Bin的Value是binary类型的,所以,我们成功的接收了这个bit串。

    更多关于bit串的处理,参见: http://user.it.uu.se/~pergu/papers/erlang05.pdf  

  • 相关阅读:
    原生ES-Module在浏览器中的尝试
    常见的web攻击总结
    node第三方模块----nodemailer发送邮件
    08----mockjs处理前端传来的路径,获取?后面的值
    07----mockjs获取前端传递的数据
    05-----Mock.Random 扩展方法
    03----Mock.mock() 生成接口,随机数据
    06----Mock.setup()
    十一. for of
    十.数组解构
  • 原文地址:https://www.cnblogs.com/pied/p/3637696.html
Copyright © 2011-2022 走看看