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

Erlang第二课 ---- bit串的更多相关文章

  1. 【Linux探索之旅】第二部分第二课:命令行,世界尽在掌握

    内容简介 1.第二部分第二课:命令行,世界尽在掌握 2.第二部分第三课预告:文件和目录,组织不会亏待你 命令行,世界尽在掌握 今天的标题是不是有点霸气侧漏呢? 读者:“小编,你为什么每次都要起这么非主 ...

  2. CI(CodeIgniter)框架入门教程——第二课 初始MVC

    本文转载自:http://www.softeng.cn/?p=53 今天的主要内容是,使用CodeIgniter框架完整的MVC内容来做一个简单的计算器,通过这个计算器,让大家能够体会到我在第一节课中 ...

  3. OpenCV 第二课 认识图像的存储结构

    OpenCV 第二课 认识图像的存储结构 Mat Mat 类包含两部分,矩阵头和矩阵体.矩阵头包含矩阵的大小,存储方式和矩阵体存储空间的指针.因此,Mat中矩阵头的大小是固定的,矩阵体大小是不定的. ...

  4. Kali Linux Web 渗透测试视频教程— 第二课 google hack 实战

    Kali Linux Web 渗透测试— 第二课 代理简介 文/玄魂 课程地址: http://edu.51cto.com/course/course_id-1887.html 目录 shellKal ...

  5. 【第二课】深入理解Handler

    简要讲解Handler是做什么的 我们知道,在Android中,app启动会启动一个进程一个线程——UI线程,UI线程是主线程,并且不允许这个线程阻塞超过5秒,一旦超过5秒就会ANR. 所以较为耗时的 ...

  6. ruby代码重构第二课

    (文章都是从我的个人主页上粘贴过来的, 大家也可以访问我的主页 www.iwangzheng.com) 在第一课里提取出了相通的代码,第二课里就把常量提取出来吧 一般把常量的定义写的对应的app/mo ...

  7. NeHe OpenGL教程 第二课:多边形

    前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢 ...

  8. Spark 3000门徒第二课scala面向对象总结

    昨晚听了王家林老师3000门徒spark系列课程的第二课,讲述了scala面向对象知识,并且带着过了一遍Spark核心类:SparkContent,RDD的代码,下面写一下心得: RDD是抽象类,实现 ...

  9. grails2.3.11第二课

    第二课主要介绍grails相关插件的使用,这是敏捷开发所必需的途径. 可以把grails的插件看作是grails正常项目的迷你型,因为看插件的源码,它的目录结构和正常项目相差无几. 官方开源插件地址 ...

随机推荐

  1. 在Function对象上扩展method方法

    ;(function() { /** * 在Function对象上扩展method方法 * @param {String} name 扩展的方法名称 * @param {Function} callb ...

  2. 整理MAC下Eclipse的常用快捷键

    整理Eclipse常用快捷键 开发环境切换到Mac下后原来Window下的快捷键很大一部分是不相容的,习惯了快捷键的生活忽然哪天快捷键不起作用了,跟着的就是开发效率明显降低,频繁录入错误的快捷键让Ec ...

  3. 【夯实Mysql基础】MySQL在Linux系统下配置文件及日志详解

    本文地址 分享提纲: 1. 概述 2. 详解配置文件 3. 详解日志 1.概述 MySQL配置文件在Windows下叫my.ini,在MySQL的安装根目录下:在Linux下叫my.cnf,该文件位于 ...

  4. [IPSEC PKI]

    PKI: 对称加密 非对称加密(混合加密) 数字签名   理论概述: (1)预备知识 对称加密:加密密钥和揭秘蜜钥是同一个密钥 缺点:不适合在互联网上传输密钥 密钥维护工作量大 n(n-1)/2 : ...

  5. U3D5.3.5f Monodevelop 仅支持到.NET 3.5

    2016年12月2号:发现这个标题是错误的,可以在monodevelop中选择.NET的版本,如下:打开solution,右击 Assembly-CSharp,options, build, gene ...

  6. connect函数详解

    不得不说,客户端的connect函数和服务端的accept函数是一对好基友,如果客户端没有去connect, 那么服务端的accept会一直在那里傻傻地痴痴地等待,我们先来看看connect函数的原型 ...

  7. ASP.NET中进行消息处理(MSMQ) 一

    MSMQ是微软消息队列的英文缩写.那么什么是消息队列?这些介绍网上一大片这里就不多说了.本文对于大虾级的人物来说这只是小玩意而已,对于初学者来说这文章还是有一定的帮助,希望路过的大虾们别笑话我班门弄斧 ...

  8. Python快速教程 尾声(转)

    原文地址: http://www.cnblogs.com/vamei/p/3603046.html 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留 ...

  9. WebAPI使用多个xml文件生成帮助文档(转)

    http://www.cnblogs.com/idoudou/p/xmldocumentation-for-web-api-include-documentation-from-beyond-the- ...

  10. Android开发探秘之三:利用jsoup解析HTML页面

    这节主要是讲解jsoup解析HTML页面.由于在android开发过程中,不可避免的涉及到web页面的抓取,解析,展示等等,所以,在这里我主要展示下利用jsoup jar包来抓取cnbeta.com网 ...