Erlang 位串和二进制数据
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=25876834&id=3300393
因为在本人工作中,服务端Erlang和客户端的flash通信都是发送二进制数据(协议)来通信,Erlang处理起来二进制数据真的很方便,在空余时间查看和翻译了Erlang的二进制相关一些说明文档,当然里面也有根据自己的经验和知识理解的地方。
点击(此处)折叠或打开
- Erlang 位串和二进制数据
- 位串(bitstring)是由一些有比特(bit,理解为‘位’)组成,不要求包含的比特数量能够整除8,如果恰好能够整除8的话,那么这个位串就是个binary。
- 位串中的每一个位都位于确定的一个段中,一个段由一串连续的位组成(段之间没有界限),如首位是第一个段,紧接着就是第二个段。
- 下面的例子演示了二进制数据的构造,匹配,还有如何获取和使用二进制数据中的元素。
- 1. 一些简单的例子
- 例一:
- 一个二进制数据由一组常量或者简单字符串构成
- Bin11 = <<1, 17, 42>>,
- Bin12 = <<"abc">>
- 产生的二进制数据大小为3,binary_to_list(Bin11)计算结果是[1, 17, 42], binary_to_list(Bin22)计算结果是 [97, 98, 99].
- 例二:
- 类似的,一个二进制数据也可以由一组已绑定的变量构成
- A = 1, B = 17, C = 42,
- Bin2 = <<A, B, C:16>>
- 产生的二进制数据大小为4,binary_to_list(Bin2)计算结果是 [1, 17, 0, 42]。这里C使用了尺寸表达式(size expression),指定了C这个段在二进制数据中占用16位,也就是两个单位长度。
- 例三:
- 二进制数据也可以进行匹配操作。假设D,E,F是自由变量,Bin2为例二中的变量:
- <<D:16, E, F/binary>> = Bin2
- 结果 D = 273,(因为D包含了A,B两个段,二进制转换为10进制之后的结果),E = 0,F = 42(这里在我的机器上是 <<*>>,我的erlang版本比文档上的版本新)
- 2.注意
- 语法上应该要注意的地方, "B=<<1>>" 这样的写法会被erlang编译器理解为 "B =< <1>>" ,这样就会产生语法错误。正确的写法应该是 "B = <<1>>" 。
- 3.二进制数据各个部分介绍
- 位串中,每一个段都遵循通用的语法格式,如下:
- Value:Size/TypeSpecifierList 值:大小/类型
- 因为Size和TypeSpeciferList不是必须指明的,所以在书写的时候它们可以省略,下面的格式是正确的:
- Value
- Value:Size
- Value/TypeSpecifierList
- 当没有指明使用什么规范时,就使用默认值(默认规范,也可以理解为默认语法约定)。默认值会在下面解释
- 在构造二进制数据结构的时候,Value可以是任何表达式;在进行二进制的匹配操作时,Value必须是一个普通的单词(literal )或者变量。
- Size 指明该段占多少位,要是指明了 TypeSpecifierList (类型),Size表示的多少个单位长度,size必须是整数。
- TypeSpecifierList 由 ‘-’ 隔开的一组属性组成,可以由四个部分构成:
- Type 类型,可以是 Integer, Float, Binary
- Signedness 规定是无符号还是有符号
- Endianness 规定字节存储序列
- Unit 单位长度,必须能被Size 整除
- 如:
- X:4/little-signed-integer-unit:8
- X 的总大小是 4 * 8 = 32 bit啰
- 4.默认(约定)
- 二进制中每个段的数据类型默认是整型,默认的类型不依赖于值,即便值是一个单词。
- 类似的, "<<3.14>>" 的类型也是整型,不是浮点型。
- 默认的大小(Size)由类型决定,整型是8,浮点是64,如果是binary类型的话就是该binary的整个长度。在匹配操作中,只有最后一段数据使用默认大小才是合法的,其他位置的数据段必须指定大小。
- 默认的单位长度,整型和浮点都是1,binary是8.
- 默认是无符号
- 默认的字节序列是大头排列
- 5.构造一个binary 和 位串(bitstring)
- 构造二进制的语法和创建列表和元组不一样,如果参数错误的话,会爆出 “badarg”的错误。
- 一个二进制可以由一个或多个段构成,0个段 “<<>>”表示大小为零的二进制数据(很多时候,我们会发空 的二进制作为触发没个事件的信号)。
- <<Bin/binary,Bitstring/bitstring>>
- 这样一个数据,Bin的大小一定是8比特的整数倍,而Bitstring的大小一定是1的整数倍。
- 下面的数据:
- <<X:1, Y:6>>
- 可以成功构造一个大小为7bit的位串,特别的提出一点:
- <<X+1:8>> 是错误的,应该写作:
- <<(X+1):8>>
- <<"hello">> 等价于 <<$h,$e,$l,$l,$o>> ,前者在语法上比后者更加便利(语法糖)
- 6.二进制数据的匹配操作
- 匹配操作的时候,记住Size一定是一个整数或者绑定的变量(值为整数),如
- foo(N, <<X:N,T/binary>>) ->
- {X,T}.
- 这样是错误的,因为在编译的时候,N作为Size还没有绑定。
- 正确的做法:
- foo(N, Bin) ->
- <<X:N,T/binary>> = Bin,
- {X,T}.
- 7.获取一个二进制和位串的剩余部分
- foo(<<A:8,Rest/binary>>) ->
- Rest的大小一定能整除8
- foo(<<A:8,Rest/bitstring>>) ->
- Rest的大小没有严格限制了
- 8.位串解析(Bit String Comprehensions)
- 位串解析类似列表解析,是一种非常高效的产生新的位串的方法,一般语法如下:
- << BitString || Qualifier1,...,QualifierN >>
- BitString一个合法的位串表达式,Qualifier是位串生成器或者过滤器
- 一般的生成器(如列表解析里面),通常写作:
- Pattern <- ListExpr.
- 而位串生成器写作:
- BitstringPattern <= BitStringExpr.
- 当然了,这里BitStringExpr 肯定一个合法的位串表达式
- 过滤器是一个返回true或false的表达式
- 具体的例子:
- << << (X*2) >> || <<X>> <= << 1,2,3 >> >>.
- <<2,4,6>>
- 1.BIF:
- BIF:(built-in function)内建函数,是erlang语言的组成部分。是erlang虚拟机中的基本操作。
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
作用:可以对存储了任何类型的列表进行排序,并根据比较顺序,编写高效的数据访问代码。
出了=:=,=/=外,其他都遵循下面规则:
如果一个比较参数为整数,另一个浮点数, 整数在比较前需要转换成浮点数。
如果两个比较参数都是整数或者浮点数,直接比较。。。
==只适用于浮点数和整数的比较。最好都用=:=。
下划线变量:
如果一个变量在一个字句中只被使用一次,编译器会提出警告。但以下划线开始,那么编译器不会产生警告信息。
命名不准备使用的变量,增加可读性。方便调试。
Erlang 位串和二进制数据的更多相关文章
- php 将16进制数串转换为二进制数据的函数
/** * 将16进制数串转换为二进制数据的函数 * @param $hexdata * @return string bindata */ function ...
- 转载:【原译】Erlang构建和匹配二进制数据(Efficiency Guide)
转自:http://www.cnblogs.com/futuredo/archive/2012/10/19/2727204.html Constructing and matching binarie ...
- erlang二进制数据垃圾回收机制
erlang二进制数据在内存中有两种存在形式,当数据大小不到 64 bytes,就直接存在进程堆内.假设超过了64 bytes.就被保存到进程外的共享堆里,能够给节点内全部进程共享. erlang有两 ...
- atitit.无损传输二进制数据串传输网络
atitit.无损传输二进制数据串传输网络 1. gbk的网络传输问题,为什么gbk不能使用来传输二进制数据 1 2. base64 2 3. iso-8859-1 (推荐) 2 4. utf-8 ...
- 转载: Erlang Socket解析二进制数据包
转自:http://www.itkee.com/developer/detail-318.html 今天在家里闲来无事,实践了一下Erlang的Socket的功能.记录一下在过程中遇到的一些问题,以及 ...
- 巧用AWK处理二进制数据文件
AWK是Unix下的一款功能强大的文本格式化和抽取工具.利用这个工具,可以对复杂的文本文件进行整理,提取其中的全部或者部分数据,按照需要的格式予以显示.需要说明的是,AWK的强大功能只针对纯文本文件. ...
- QDataStream类参考(串行化数据,可设置低位高位,以及版本号),还有一个例子
QDataStream类提供了二进制数据到QIODevice的串行化. #include 所 有成员函数的列表. 公有成员 QDataStream () QDataStream ( QIODevice ...
- 详细解读XMLHttpRequest(二)响应属性、二进制数据、监测上传下载进度
本文主要参考:MDN 分析并操作 responseXML属性 如果你使用 XMLHttpRequest 来获得一个远程的 XML 文档的内容,responseXML 属性将会是一个由 XML 文档解析 ...
- 讨论贴:Sqlserver varbinary 是二进制数据,却是十六进制的表现形式
首先创建一个数据表 CREATE TABLE [dbo].[log_info]( [id] [,) NOT NULL, [info] [varchar]() NULL, [info1] [varbin ...
随机推荐
- xcode6.3 模版位置
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templ ...
- JQuery的index()函数
1.index(),这里的索引从0开始计数. jQueryObject.index( [ object ] ):1.1 如果没有指定参数object,则返回当前元素在其所有同辈元素中的索引位置.1.2 ...
- Java基础学习总结(53)——HTTPS 理论详解与实践
前言 在进行 HTTP 通信时,信息可能会监听.服务器或客户端身份伪装等安全问题,HTTPS 则能有效解决这些问题.在使用原始的HTTP连接的时候,因为服务器与用户之间是直接进行的明文传输,导致了用户 ...
- 字符串中的空格替换问题(Java版)
解决方式一:时间复杂度为O(n^2) 解决方式二:时间复杂度为O(n) 代码实现: package string; public class SpaceStringReplace2 { //len为数 ...
- What is corresponding Cron expression to fire in every X seconds, where X > 60? --转载
原文地址:http://stackoverflow.com/questions/2996280/what-is-corresponding-cron-expression-to-fire-in-eve ...
- Loadrunner--负载生成器
对场景进行设计后,接着需要对负载生成器进行管理和设置.Load Generator是运行脚本的负载引擎,在默认情况下使用本地的负载生成器来运行脚本,但是模拟用户行为也需要消耗一定的系统资源,所以在一台 ...
- C# 泛型特化
C# 泛型不是 C++ 的模板类,并不支持特化和偏特化,但是使用一些技巧可以在一定程度上达到相同的目的. 原文是 po 在 stackoverflow 上的一个回答:A: Generic indexe ...
- 学习C#修饰符:类修饰符和成员修饰符
C#修饰符之类修饰符:public.internal. partial.abstract.sealed.static C#修饰符之成员修饰符:public.protected.private.inte ...
- IIS7配置PHP图解
IIS6整合PHP详解:http://zhidao.zgsj.com/article/8/2011118142648.shtml PHP5.2.17 官方下载: http://windows.php. ...
- php实现 计算字符串的距离
php实现 计算字符串的距离 一.总结 一句话总结:解决dp问题最好的方法是什么:分析出状态后 实例+画表. 1.解决dp问题最好的方法是什么? 分析出状态后 实例+画表 2.画图的好处? 画出来表之 ...