Erlang 位串和二进制数据

 

http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=25876834&id=3300393

因为在本人工作中,服务端Erlang和客户端的flash通信都是发送二进制数据(协议)来通信,Erlang处理起来二进制数据真的很方便,在空余时间查看和翻译了Erlang的二进制相关一些说明文档,当然里面也有根据自己的经验和知识理解的地方。

在二进制解析部分,其实还有很多好的例子。还有就是Erlang的二进制实际应用的例子,下次会再分享的,翻译不到位的地方,还请多多指正,原文地址
http://www.erlang.org/doc/programming_examples/bit_syntax.html#id64786,
http://www.erlang.org/doc/reference_manual/expressions.html#id79300

点击(此处)折叠或打开

  1. Erlang 位串和二进制数据
  2.     位串(bitstring)是由一些有比特(bit,理解为‘位’)组成,不要求包含的比特数量能够整除8,如果恰好能够整除8的话,那么这个位串就是个binary。
  3. 位串中的每一个位都位于确定的一个段中,一个段由一串连续的位组成(段之间没有界限),如首位是第一个段,紧接着就是第二个段。
  4. 下面的例子演示了二进制数据的构造,匹配,还有如何获取和使用二进制数据中的元素。
  5. 1. 一些简单的例子
  6. 例一
  7.     一个二进制数据由一组常量或者简单字符串构成
  8. Bin11 = <<1, 17, 42>>,
  9. Bin12 = <<"abc">>
  10. 产生的二进制数据大小为3,binary_to_list(Bin11)计算结果是[1, 17, 42], binary_to_list(Bin22)计算结果是 [97, 98, 99].
  11. 例二
  12.     类似的,一个二进制数据也可以由一组已绑定的变量构成
  13. A = 1, B = 17, C = 42,
  14. Bin2 = <<A, B, C:16>>
  15. 产生的二进制数据大小为4,binary_to_list(Bin2)计算结果是 [1, 17, 0, 42]。这里C使用了尺寸表达式(size expression),指定了C这个段在二进制数据中占用16位,也就是两个单位长度。
  16. 例三
  17.     二进制数据也可以进行匹配操作。假设D,E,F是自由变量,Bin2为例二中的变量:
  18.  <<D:16, E, F/binary>> = Bin2
  19. 结果 D = 273,(因为D包含了A,B两个段,二进制转换为10进制之后的结果),E = 0,F = 42(这里在我的机器上是 <<*>>,我的erlang版本比文档上的版本新)
  20. 2.注意
  21.     语法上应该要注意的地方, "B=<<1>>" 这样的写法会被erlang编译器理解为 "B =< <1>>" ,这样就会产生语法错误。正确的写法应该是 "B = <<1>>" 。
  22. 3.二进制数据各个部分介绍
  23.     位串中,每一个段都遵循通用的语法格式,如下:
  24. Value:Size/TypeSpecifierList 值:大小/类型
  25. 因为Size和TypeSpeciferList不是必须指明的,所以在书写的时候它们可以省略,下面的格式是正确的:
  26. Value
  27. Value:Size
  28. Value/TypeSpecifierList
  29. 当没有指明使用什么规范时,就使用默认值(默认规范,也可以理解为默认语法约定)。默认值会在下面解释
  30. 在构造二进制数据结构的时候,Value可以是任何表达式;在进行二进制的匹配操作时,Value必须是一个普通的单词(literal )或者变量。
  31. Size 指明该段占多少位,要是指明了 TypeSpecifierList (类型),Size表示的多少个单位长度,size必须是整数。
  32. TypeSpecifierList 由 ‘-’ 隔开的一组属性组成,可以由四个部分构成:
  33.     Type 类型,可以是 Integer, Float, Binary
  34.     Signedness 规定是无符号还是有符号
  35.     Endianness 规定字节存储序列
  36.     Unit 单位长度,必须能被Size 整除
  37. 如:
  38.     X:4/little-signed-integer-unit:8
  39.     X 的总大小是 4 * 8 = 32 bit啰
  40. 4.默认(约定)
  41.     二进制中每个段的数据类型默认是整型,默认的类型不依赖于值,即便值是一个单词。
  42. 类似的, "<<3.14>>" 的类型也是整型,不是浮点型。
  43.   默认的大小(Size)由类型决定,整型是8,浮点是64,如果是binary类型的话就是该binary的整个长度。在匹配操作中,只有最后一段数据使用默认大小才是合法的,其他位置的数据段必须指定大小。
  44.   默认的单位长度,整型和浮点都是1,binary是8.
  45.   默认是无符号
  46.   默认的字节序列是大头排列
  47. 5.构造一个binary 和 位串(bitstring)
  48.     构造二进制的语法和创建列表和元组不一样,如果参数错误的话,会爆出 “badarg”的错误。
  49.     一个二进制可以由一个或多个段构成,0个段 “<<>>”表示大小为零的二进制数据(很多时候,我们会发空     的二进制作为触发没个事件的信号)。
  50.    <<Bin/binary,Bitstring/bitstring>>
  51.     这样一个数据,Bin的大小一定是8比特的整数倍,而Bitstring的大小一定是1的整数倍。
  52.     下面的数据:
  53.     <<X:1, Y:6>> 
  54.     可以成功构造一个大小为7bit的位串,特别的提出一点:
  55.     <<X+1:8>> 是错误的,应该写作:
  56.     <<(X+1):8>>
  57.     <<"hello">> 等价于 <<$h,$e,$l,$l,$o>> ,前者在语法上比后者更加便利(语法糖)
  58. 6.二进制数据的匹配操作
  59.     匹配操作的时候,记住Size一定是一个整数或者绑定的变量(值为整数),如
  60.     foo(N, <<X:N,T/binary>>) ->
  61.     {X,T}.
  62.     这样是错误的,因为在编译的时候,N作为Size还没有绑定。
  63.     正确的做法:
  64.     foo(N, Bin) ->
  65.        <<X:N,T/binary>> = Bin,
  66.        {X,T}.
  67. 7.获取一个二进制和位串的剩余部分
  68.     foo(<<A:8,Rest/binary>>) -> 
  69.        Rest的大小一定能整除8
  70.     foo(<<A:8,Rest/bitstring>>) ->
  71.        Rest的大小没有严格限制了
  72. 8.位串解析(Bit String Comprehensions)
  73.     位串解析类似列表解析,是一种非常高效的产生新的位串的方法,一般语法如下:
  74.     << BitString || Qualifier1,...,QualifierN >>
  75.     BitString一个合法的位串表达式,Qualifier是位串生成器或者过滤器
  76.     一般的生成器(如列表解析里面),通常写作:
  77.       Pattern <- ListExpr. 
  78.     而位串生成器写作:
  79.      BitstringPattern <= BitStringExpr. 
  80.     当然了,这里BitStringExpr 肯定一个合法的位串表达式
  81.     
  82.     过滤器是一个返回true或false的表达式
  83.     具体的例子:
  84.     << << (X*2) >> || <<X>> <= << 1,2,3 >> >>.
  85.     <<2,4,6>>
  86. 1.BIF:
  87. BIF:(built-in function)内建函数,是erlang语言的组成部分。是erlang虚拟机中的基本操作。
  88. tuple_to_list/1将元组转换为列表,time/0返回当前时间的时,分,秒。
    1> tuple_to_list({12,cat,”ddd”}).
    [12,cat,"ddd"]
    3> time().
    {12,35,57}

    2.二进制数据:
    一种数据类型,用来实现原始数据的高速存储。节省内存,输入输出更加高效。书写打印时,二进制数据以一个整数或者字符序列的形式出现,两端分别用尖括号括起来。其中的整数,每一个都要在0-255之间,如果二进制数据是可以打印的字符串,shell将显示字符串形式,否则会显示一串整数。

    @spec 描述函数的参数和返回类型。类型标注,不是erlang代码而是注释文档的一部分,shell中不能使用这些标注。erlang中的模块声明也是注释的一部分。

    erlang通过BIF来构造二进制数据或者从中提取数据,或者通过比特语法来完成这一过程。
    @spec list_tbo_inary(IoList) -> binary()
    @spec split_binary(Bin,Pos) -> {Bin1,Bin2}
    @spec term_to_binary(Term) -> Bin
    @spec binary_to_term(Bin) -> Term
    list_tbo_inary将IoList中所有东西转换为一个二进制数据。split_binary在pos位置将二进制数据分割成两个部分。下面两个是互逆。

    4> Bin1 = <<1,2,3>>.
    <<1,2,3>>
    5> Bin2 = <<4,5>>.
    <<4,5>>
    6> Bin3 = <<6>>.
    <<6>>
    7> list_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]).
    <<1,2,3,1,2,3,4,5,4,6>>
    12> split_binary(<<1,2,3,1,2,3,4,5,4,6>>,4).
    {<<1,2,3,1>>,<<2,3,4,5,4,6>>
    14> term_to_binary({11,’333a’,use}).
    <<131,104,3,97,11,100,0,4,51,51,51,97,100,0,3,117,115,101>>
    15> binary_to_term(<<131,104,3,97,11,100,0,4,51,51,51,97,100,0,3,117,115,101>>).
    {11,’333a’,use}
    返回二进制数据字节长度
    16> size(<<1,2,3,4>>).
    4
    3.比特语法
    比特语法:一种模式匹配语法,用于二进制数据中的比特进行封包和解包工作。
    比特语法是模式匹配的一种扩展。编写底层代码时,常会需要对比特级别的二进制数据进行封包解包,会体现比特语法的便捷,比特语法针对协议编程而设计(erlang的看家本领 哇塞)。
    16bit色彩的封包解包

    19> Red = 2.
    2
    20> Green = 54.
    54
    21> Blue = 20.
    20
    22> Men = <<Red:5,Green:6,Blue:5>>.
    <<22,212>>
    23> Mem = <<Red:5,Green:5,Blue:5>>.
    <<21,84:7>>
    24> <<R1:5,G1:6,B1:5>> = Men.
    <<22,212>>
    25> R1.
    2
    27> G1.
    54
    28> B1.
    20

    可以看到是用:进行匹配,冒号前是数据,后是所占的比特数。

    比特语法表达式

    嗯,这里讲比特语法格式:

    比特语法的形式:<<>>或者<<E1,E2,E3,E4,…,En>>。Ei有四种形式:

    Ei = Value | Value:Size | Value/TypeSpecifierList | Value:Size/TypeSpecifierList

    二进制数据中总比特数恰好被8整除(二进制数据中每个字节都是8bit)。Value必须是一个绑定变量、文本串或者一个返回值的整数。浮点数、二进制数据的表达式。Size必须为一个整型或者整型绑定变量,不能是自由变量。整型默认Size为8,浮点型为64,二进制则为本身长度。SpecifierList决定字节序,取值为:

    @type End = big| little |native

    书上给出一个例子来了解这三种排序和默认排序,不同机器可能不同。

    37> {<<16#12345678:32/big>>,<<16#12345678:32/little>>,<<16#12345678:32/native>>,<<16#12345678:32>>}.
    {<<18,52,86,120>>,
    <<120,86,52,18>>,
    <<120,86,52,18>>,
    <<18,52,86,120>>}

    4.使用总结

    块表达式:

    begin
    Expr1,
    ….
    Exprn
    end

    块得值就是快中最后一个表达式的值,用于当代码某处只允许使用单个表达式而你要用一串表达式时。

    注释:

    只有行注释%,没有块注释。

    列表操作符++ ——:对列表进行添加和删除的中缀操作符。

    比较表达式:

    所有类型都定义了大小比较顺序:

    number<atom<reference<fun<port<pid<tuple<list<binary

    作用:可以对存储了任何类型的列表进行排序,并根据比较顺序,编写高效的数据访问代码。

    出了=:=,=/=外,其他都遵循下面规则:

    如果一个比较参数为整数,另一个浮点数, 整数在比较前需要转换成浮点数。

    如果两个比较参数都是整数或者浮点数,直接比较。。。

    ==只适用于浮点数和整数的比较。最好都用=:=。

     

    下划线变量:

    如果一个变量在一个字句中只被使用一次,编译器会提出警告。但以下划线开始,那么编译器不会产生警告信息。

    命名不准备使用的变量,增加可读性。方便调试。

转载于:https://www.cnblogs.com/fvsfvs123/p/4241194.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459696.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于webstorm 配置 banbel

2019独角兽企业重金招聘Python工程师标准>>> file type : javascript files scope: project files program: ..............appData\Roaming\npm\babel.cmd argumemt: $FileName$ --out-file $FileNameWithoutExtension$.js -s ps: --out-put 输出es5 格式的文件 …

php imap 附件,学习猿地-PHP-imap 使用参考

1. 相关资料php-imap 用于获取邮件 &#xff0c;但是没有详细的官方文档 &#xff0c;在这里整理一份分享给大家composer require php-imap/php-imap2. php-imap 成员2.1 构造方法参数说明示例$imapPath服务地址{imap.163.com:143}$login登录名email163.com$password登录密码**…

微信朋友圈广告详细说明

根据官方发布的微信广告系统介绍&#xff0c;朋友圈广告来源于微信广告的一部分&#xff0c;与公众号广告形成了一整个体系。关于公众号的广告&#xff0c;简单说&#xff0c;他可以把微信公众号变成广告牌&#xff0c;会根据用户的阅读习惯以及个人信息来进行广告的投放。每一…

EasyExcel 导出文件的格式化

阿里开源的这个库&#xff0c;让 Excel 导出不再复杂&#xff08;既要能写&#xff0c;还要写的好看&#xff09; 之前聊了 EasyExcel 的内容导出&#xff0c;本文主要说一下导出文件的格式化&#xff0c;格式化包括工作表/单元格样式和内容格式化。毕竟&#xff0c;有时候还是…

JSON数组分配输出每个li

有这么一个JSON数组&#xff0c;需求是只需要输出每个数组里面的某个值&#xff0c;不需要全部输出来。 var data [ {"MachineID":"171914","Cost":"13,642.41","Currency":"PHP" }, {"MachineID":&qu…

[BZOJ 3236] [Ahoi2013] 作业 [BZOJ 3809] 【莫队(+分块)】

题目链接&#xff1a; BZOJ - 3236 BZOJ - 3809 算法一&#xff1a;莫队 首先&#xff0c;单纯的莫队算法是很好想的&#xff0c;就是用普通的第一关键字为 l 所在块&#xff0c;第二关键字为 r 的莫队。 这样每次端点移动添加或删除一个数字&#xff0c;用树状数组维护所求的…

武汉理工大学java,武汉理工大学 web技术基础

计算机网络是现代通信技术与计算机技术相结合的产物&#xff0c;Internet则是计算机网络的最具体的应用。Web服务是最主要的网络服务&#xff0c;几乎一提到Internet&#xff0c;就会想到Web技术。本课程将介绍互联网的发展历史&#xff0c;最新的科学进展&#xff0c;Web的工作…

mysql多实例

mysql的多实例有两种方式可以实现&#xff0c;两种方式各有利弊。第一种是使用多个配置文件启动不同的进程来实现多实例&#xff0c;这种方式的优势逻辑简单&#xff0c;配置简单&#xff0c;缺点是管理起来不太方便。第二种是通过官方自带的mysqld_multi使用单独的配置文件来实…

oracle闪回某个时间点的数据库,oracle11g 使用闪回查询恢复表到过去某一个时间点...

一、新建测试表并插入数据&#xff1a;oracle二、模拟表数据误删并提交&#xff1a;测试三、使用闪回查询来查误删前表的数据&#xff1a;(表误删是在15:08分左右误删&#xff0c;所以在15:08分以前表的数据仍是在的)&#xff1a;spa四、用如今的数据与误删前的数据作对比&…

opengl微开发之1-从零開始

对OpenGL有一点了解之后&#xff0c;如今開始真正编写代码。 今天的内容&#xff1a; 使用FreeGLUT创建OpenGL的上下文环境 初始化GLEW 创建一个OpenGL的的模板范例 第一步&#xff1a; 一个OpenGL的上下文能够同意我们传递命令究竟层硬件&#xff0c;所以须要一个上下文环境。…

Git客户端(Windows系统)的使用(Putty)(转)

本文环境&#xff1a; 操作系统&#xff1a;Windows XP SP3 Git客户端&#xff1a;TortoiseGit-1.8.14.0-32bit 一、安装Git客户端 全部安装均采用默认&#xff01; 1. 安装支撑软件 msysgit: http://msysgit.github.io/ 当前最新版本为v1.9.5。 2. 安装TortoiseGit 首先&#…

oracle只舍不入,Oracle常识基础(一)

一.Oracle数据类型1.字符数据类型.> char:可以存储字母数字值&#xff0c;长度在1到2000个字节。.> varchar2:存储可变长度的char类型字符串,大小在1到4000个字节范围内。.> long:存储可变长度的字符数据,最多存储2GB。long类型的使用限制&#xff1a;*********…

软件测试的误区

随着软件测试对提高软件质量重要性的不断提高&#xff0c;软件测试也不断受到重视。但是&#xff0c;国内软件测试过程的不规范&#xff0c;重视开发和轻视测试的现象依旧存在。因此&#xff0c;对于软件测试的重要性、测试方法和测试过程等方面都存在很多不恰当的认识&#xf…

Kubernetes用户指南(二)--部署组合型的应用、连接应用到网络中

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/qq1010885678/article/details/49026825 一、部署组合型的应用1、使用配置文件启动replicas集合k8s通过Replication Controller来创建和管理各个不同的重复容器集合&#xff…

oracle指令df,​ oracle 常用命令大汇总

oracle常用命令大汇总第一章&#xff1a;日志管理1、forcing log switchessql> alter system switch logfile;2、forcing checkpointssql> alter system checkpoint;3、adding online redo log groupssql> alter database add logfile [group 4]sql> (/disk3/log4a…

时刻获取浏览器宽度

$(function(){$(window).resize(Nchwid);function Nchwid() {var widdocument.documentElement.clientWidth;console.log(wid); }}) 转载于:https://www.cnblogs.com/nc-blog/p/4250132.html

oracle 函数

运算符: 算数运算符: - * / 连接运算符 || e.g select a||b||c from dual; 比较运算符 >, , >, <, <, !, like, between and, is null, in 任何值与null进行运算 都为null ascii(a); 根据字符 返回编码值 chr(编…

oracle中defined,Oracle:专栏定义(Oracle: column ambigously defined)

Oracle&#xff1a;专栏定义(Oracle: column ambigously defined)我收到以下错误。 据我所知&#xff0c;所有列都是由表名定义的&#xff0c;所以我不明白为什么我从Oracle数据库中得到这个错误。OCIError: ORA-00918: column ambiguously defined: SELECT * FROM (SELECT raw…

两道二分coming~

第一道&#xff1a;poj 1905Expanding Rods 题意&#xff1a;两道墙&#xff08;距离L&#xff09;之间架一根棒子&#xff0c;棒子受热会变长&#xff0c;弯曲&#xff0c;长度变化满足公式&#xff08; s(1n*C)*L&#xff09;&#xff0c;求的是弯曲的高度h。 首先来看这个图…

include静态加载布局ViewStub动态加载布局

layout"layout/" 文件名.xml/> 他可以加载任何的layout如果是如果想加载一个控件&#xff0c;要把这个控件写在layout。xml文件里 ViewStub android:id"id/vsb" android:layout_width"match_parent" android:layout_height&qu…