查看源代码 binary (stdlib v6.2)
用于处理二进制数据的库。
此模块包含用于操作面向字节的二进制数据的函数。尽管大多数函数可以使用位语法提供,但此库中的函数经过高度优化,预计比用纯 Erlang 编写的对应函数执行速度更快或消耗更少的内存,或两者兼而有之。
该模块根据 Erlang 增强提案 (EEP) 31 提供。
注意
该库处理面向字节的数据。对于非二进制(不包含完整的八位字节)的位串,此模块中的任何函数都会抛出
badarg
异常。
概要
函数
以整数形式返回二进制 Subject
中位置 Pos
(基于零) 处的字节。
将 Subject
转换为 byte/0
的列表,每个 byte/0
表示一个字节的值。
将 Subject
转换为 byte/0
的列表,每个 byte/0
表示一个字节的值。PosLen
或可选的 Pos
和 Len
表示要转换的 Subject
二进制数据的哪一部分。默认情况下,将转换整个 Subject
二进制数据。
创建一个二进制数据,其中包含 Subject
的内容,并重复 N
次。
将十六进制编码的二进制数据解码为二进制数据。
将 Subject
中正整数的大端或小端二进制数字表示形式转换为 Erlang integer/0
。
使用指定的十六进制数字 "a" 到 "f" 的大小写,将二进制数据编码为十六进制编码的二进制数据。
将正整数转换为二进制数字表示形式中最小的可能表示形式,无论是大端还是小端。
以整数形式返回二进制 Subject
的第一个字节。如果 Subject
的大小为零,则会引发 badarg
异常。
以整数形式返回二进制 Subject
的最后一个字节。如果 Subject
的大小为零,则会引发 badarg
异常。
其作用与 erlang:list_to_binary/1
完全相同,为了完整性而添加。
返回列表 Binaries
中二进制数据最长公共前缀的长度。
返回列表 Binaries
中二进制数据最长公共后缀的长度。
在 Subject
中搜索 Pattern
的第一个出现,并返回位置和长度。
与 match/2
相同,但会搜索 Subject
直到耗尽,并返回所有匹配 Pattern
的非重叠部分(按顺序)的列表。
提取由 PosLen
描述的二进制 Subject
的部分。
获取 Binary
引用的底层二进制数据的大小。
通过将 Subject
中匹配 Pattern
的部分替换为 Replacement
(如果给定为文字 binary/0
) 或将 Replacement
应用于匹配的子部分 (如果给定为 fun
) 的结果,构造新的二进制数据。
根据 Pattern
将 Subject
拆分为二进制数据列表。
类型
-opaque cp()
表示已编译搜索模式的不透明数据类型。
保证是 tuple/0
,以允许程序将其与未预编译的搜索模式区分开。
-type part() :: {Start :: non_neg_integer(), Length :: integer()}.
二进制数据中的一部分(或范围)的表示。Start
是 binary/0
中基于零的偏移量,Length
是该部分的长度。
作为此模块中函数的输入,允许使用反向部分规范(使用负 Length
构造),以便二进制数据的一部分从 Start
+ Length
开始,长度为 -Length
。这对于将二进制数据的最后 N
个字节引用为 {size(Binary), -N}
非常有用。此模块中的函数始终返回具有正 Length
的 part/0
。
函数
-spec at(Subject, Pos) -> byte() when Subject :: binary(), Pos :: non_neg_integer().
以整数形式返回二进制 Subject
中位置 Pos
(基于零) 处的字节。
如果 Pos
>= byte_size(Subject)
,则会引发 badarg
异常。
将 Subject
转换为 byte/0
的列表,每个 byte/0
表示一个字节的值。
示例
1> binary:bin_to_list(<<"erlang">>).
"erlang"
%% or [101,114,108,97,110,103] in list notation.
-spec bin_to_list(Subject, Pos, Len) -> [byte()] when Subject :: binary(), Pos :: non_neg_integer(), Len :: integer().
将 Subject
转换为 byte/0
的列表,每个 byte/0
表示一个字节的值。PosLen
或可选的 Pos
和 Len
表示要转换的 Subject
二进制数据的哪一部分。默认情况下,将转换整个 Subject
二进制数据。
示例
1> binary:bin_to_list(<<"erlang">>, {1,3}).
"rla"
%% or [114,108,97] in list notation.
如果 PosLen
或可选的 Pos
和 Len
以任何方式引用二进制数据外部,则会引发 badarg
异常。
-spec compile_pattern(Pattern) -> cp() when Pattern :: PatternBinary | [PatternBinary, ...], PatternBinary :: nonempty_binary().
构建表示搜索模式编译的内部结构,该结构稍后将在函数 match/3
、matches/3
、split/3
或 replace/4
中使用。
返回的 cp/0
保证是 tuple/0
,以允许程序将其与未预编译的搜索模式区分开。
指定二进制数据列表时,它表示要搜索的一组替代二进制数据。例如,如果将 [<<"functional">>,<<"programming">>]
指定为 Pattern
,这意味着 <<"functional">>
或 <<"programming">>
"。模式是一组替代方案;当仅指定单个二进制数据时,该组只有一个元素。模式中替代方案的顺序并不重要。
用于搜索替代方案的二进制数据列表必须是扁平的、合适的且非空的。
如果 Pattern
不是二进制数据或长度 > 0 的扁平的合适非空二进制数据列表,则会引发 badarg
异常。
等效于 copy(Subject, 1)
。
-spec copy(Subject, N) -> binary() when Subject :: binary(), N :: non_neg_integer().
创建一个二进制数据,其中包含 Subject
的内容,并重复 N
次。
即使 N = 1
,此函数始终会创建新的二进制数据。通过对引用较大二进制数据的二进制数据使用 copy/1
,可以释放较大的二进制数据以进行垃圾回收。
注意
通过故意复制单个二进制数据以避免引用较大的二进制数据,可以创建比所需更多的二进制数据,而不是释放较大的二进制数据以供后续垃圾回收。共享二进制数据通常很好。只有在特殊情况下,当小部分引用大的二进制数据并且大的二进制数据不再在任何进程中使用时,故意复制才是一个好主意。
-spec decode_hex(Bin) -> Bin2 when Bin :: <<_:_*16>>, Bin2 :: binary().
将十六进制编码的二进制数据解码为二进制数据。
示例
1> binary:decode_hex(<<"66">>).
<<"f">>
-spec decode_unsigned(Subject) -> Unsigned when Subject :: binary(), Unsigned :: non_neg_integer().
-spec decode_unsigned(Subject, Endianness) -> Unsigned when Subject :: binary(), Endianness :: big | little, Unsigned :: non_neg_integer().
将 Subject
中正整数的大端或小端二进制数字表示形式转换为 Erlang integer/0
。
示例
1> binary:decode_unsigned(<<169,138,199>>).
11111111
2> binary:decode_unsigned(<<169,138,199>>, big).
11111111
3> binary:decode_unsigned(<<169,138,199>>, little).
13077161
-spec encode_hex(Bin) -> Bin2 when Bin :: binary(), Bin2 :: <<_:_*16>>.
-spec encode_hex(Bin, Case) -> Bin2 when Bin :: binary(), Case :: lowercase | uppercase, Bin2 :: <<_:_*16>>.
使用指定的十六进制数字 "a" 到 "f" 的大小写,将二进制数据编码为十六进制编码的二进制数据。
默认情况是 uppercase
。
示例
1> binary:encode_hex(<<"f">>).
<<"66">>
2> binary:encode_hex(<<"/">>).
<<"2F">>
3> binary:encode_hex(<<"/">>, lowercase).
<<"2f">>
4> binary:encode_hex(<<"/">>, uppercase).
<<"2F">>
-spec encode_unsigned(Unsigned) -> binary() when Unsigned :: non_neg_integer().
-spec encode_unsigned(Unsigned, Endianness) -> binary() when Unsigned :: non_neg_integer(), Endianness :: big | little.
将正整数转换为二进制数字表示形式中最小的可能表示形式,无论是大端还是小端。
示例
1> binary:encode_unsigned(11111111).
<<169,138,199>>
2> binary:encode_unsigned(11111111, big).
<<169,138,199>>
2> binary:encode_unsigned(11111111, little).
<<199,138,169>>
以整数形式返回二进制 Subject
的第一个字节。如果 Subject
的大小为零,则会引发 badarg
异常。
以整数形式返回二进制 Subject
的最后一个字节。如果 Subject
的大小为零,则会引发 badarg
异常。
其作用与 erlang:list_to_binary/1
完全相同,为了完整性而添加。
-spec longest_common_prefix(Binaries) -> non_neg_integer() when Binaries :: [binary(), ...].
返回列表 Binaries
中二进制数据最长公共前缀的长度。
示例
1> binary:longest_common_prefix([<<"erlang">>, <<"ergonomy">>]).
2
2> binary:longest_common_prefix([<<"erlang">>, <<"perl">>]).
0
如果 Binaries
不是一个平坦的非空二进制列表,则会引发 badarg
异常。
-spec longest_common_suffix(Binaries) -> non_neg_integer() when Binaries :: [binary(), ...].
返回列表 Binaries
中二进制数据最长公共后缀的长度。
示例
1> binary:longest_common_suffix([<<"erlang">>, <<"fang">>]).
3
2> binary:longest_common_suffix([<<"erlang">>, <<"perl">>]).
0
如果 Binaries
不是一个平坦的非空二进制列表,则会引发 badarg
异常。
-spec match(Subject, Pattern) -> Found | nomatch when Subject :: binary(), Pattern :: PatternBinary | [PatternBinary, ...] | cp(), PatternBinary :: nonempty_binary(), Found :: part().
-spec match(Subject, Pattern, Options) -> Found | nomatch when Subject :: binary(), Pattern :: PatternBinary | [PatternBinary, ...] | cp(), PatternBinary :: nonempty_binary(), Found :: part(), Options :: [Option], Option :: {scope, part()}.
在 Subject
中搜索 Pattern
的第一个出现,并返回位置和长度。
该函数返回 {Pos, Length}
,表示 Pattern
中的二进制在 Subject
中最低位置的匹配项。
示例
1> binary:match(<<"abcde">>, [<<"bcde">>, <<"cd">>],[]).
{1,4}
即使 <<"cd">>
在 <<"bcde">>
之前结束,<<"bcde">>
也会先开始匹配,因此是第一个匹配项。如果两个重叠匹配项在同一位置开始,则返回最长的匹配项。
选项摘要
- {scope, {Start, Length}} - 仅搜索指定的部分。返回值仍然具有相对于
Subject
开头的偏移量。允许使用负Length
,如本手册中“数据类型”部分所述。
如果在 Pattern
中没有找到任何字符串,则返回原子 nomatch
。
有关 Pattern
的说明,请参阅函数 compile_pattern/1
。
如果在选项中指定了 {scope, {Start,Length}}
,使得 Start
> Subject
的大小,Start
+ Length
< 0 或 Start
+ Length
> Subject
的大小,则会引发 badarg
异常。
-spec matches(Subject, Pattern) -> Found when Subject :: binary(), Pattern :: PatternBinary | [PatternBinary, ...] | cp(), PatternBinary :: nonempty_binary(), Found :: [part()].
-spec matches(Subject, Pattern, Options) -> Found when Subject :: binary(), Pattern :: PatternBinary | [PatternBinary, ...] | cp(), PatternBinary :: nonempty_binary(), Found :: [part()], Options :: [Option], Option :: {scope, part()}.
与 match/2
相同,但会搜索 Subject
直到耗尽,并返回所有匹配 Pattern
的非重叠部分(按顺序)的列表。
第一个也是最长的匹配项优先于较短的匹配项,以下示例说明了这一点
1> binary:matches(<<"abcde">>,
[<<"bcde">>,<<"bc">>,<<"de">>],[]).
[{1,4}]
结果表明选择了 <<"bcde">>
而不是较短的匹配项 <<"bc">>
(后者会产生另一个匹配项 <<"de">>
)。这与 POSIX 正则表达式(以及像 awk 这样的程序)的行为相符,但与 re
(和 Perl)中的替代匹配不一致,在 re
和 Perl 中,搜索模式中的词法顺序会选择匹配哪个字符串。
如果在模式中没有找到任何字符串,则返回一个空列表。
有关 Pattern
的说明,请参阅 compile_pattern/1
。有关可用选项的说明,请参阅 match/3
。
如果在选项中指定了 {scope, {Start,Length}}
,使得 Start
> Subject
的大小,Start + Length
< 0 或 Start + Length
> Subject
的大小,则会引发 badarg
异常。
-spec part(Subject, Pos, Len) -> binary() when Subject :: binary(), Pos :: non_neg_integer(), Len :: integer().
提取由 PosLen
描述的二进制 Subject
的部分。
可以使用负长度来提取二进制末尾的字节
1> Bin = <<1,2,3,4,5,6,7,8,9,10>>.
2> binary:part(Bin, {byte_size(Bin), -5}).
<<6,7,8,9,10>>
注意
part/2
和part/3
也可在erlang
模块中以binary_part/2
和binary_part/3
的名称使用。这些 BIF 允许在 guard 测试中使用。
如果 PosLen
以任何方式引用二进制外部,则会引发 badarg
异常。
-spec referenced_byte_size(Binary) -> non_neg_integer() when Binary :: binary().
获取 Binary
引用的底层二进制数据的大小。
如果一个二进制引用了一个更大的二进制(通常被描述为子二进制),那么获取被引用的二进制的大小可能很有用。此函数可在程序中用于触发 copy/1
的使用。通过复制二进制,可以取消对原始的、可能很大的二进制的引用,而较小的二进制是对其的引用。
示例
store(Binary, GBSet) ->
NewBin =
case binary:referenced_byte_size(Binary) of
Large when Large > 2 * byte_size(Binary) ->
binary:copy(Binary);
_ ->
Binary
end,
gb_sets:insert(NewBin,GBSet).
在此示例中,我们选择在将二进制内容插入 gb_sets:set()
之前复制它,如果它引用的二进制大小是我们要保留的数据大小的两倍以上。当然,复制到不同程序时适用不同的规则。
每当二进制被拆分时,就会发生二进制共享。这是二进制速度快的基本原因,分解始终可以以 O(1) 复杂度完成。在极少数情况下,这种数据共享是不可取的,因此在优化内存使用时,此函数与 copy/1
结合使用会很有用。
二进制共享示例
1> A = binary:copy(<<1>>, 100).
<<1,1,1,1,1 ...
2> byte_size(A).
100
3> binary:referenced_byte_size(A).
100
4> <<B:10/binary, C:90/binary>> = A.
<<1,1,1,1,1 ...
5> {byte_size(B), binary:referenced_byte_size(B)}.
{10,10}
6> {byte_size(C), binary:referenced_byte_size(C)}.
{90,100}
在上面的示例中,小的二进制 B
被复制,而较大的二进制 C
引用了二进制 A
。
注意
二进制数据在进程之间共享。如果另一个进程仍然引用较大的二进制,则复制此进程使用的部分只会消耗更多内存,并且不会释放较大的二进制以进行垃圾回收。请极其谨慎地使用此类侵入性函数,并且仅在检测到实际问题时才使用。
-spec replace(Subject, Pattern, Replacement, Options) -> Result when Subject :: binary(), Pattern :: PatternBinary | [PatternBinary, ...] | cp(), PatternBinary :: nonempty_binary(), Replacement :: binary() | fun((binary()) -> binary()), Options :: [Option], Option :: global | {scope, part()} | {insert_replaced, InsPos}, InsPos :: OnePos | [OnePos], OnePos :: non_neg_integer(), Result :: binary().
通过将 Subject
中匹配 Pattern
的部分替换为 Replacement
(如果给定为文字 binary/0
) 或将 Replacement
应用于匹配的子部分 (如果给定为 fun
) 的结果,构造新的二进制数据。
如果将 Replacement
作为 binary/0
给出,并且 Subject
的匹配子部分(产生替换)要插入到结果中,则选项 {insert_replaced, InsPos}
会将匹配的部分在将 Replacement
插入到 Subject
之前,插入到 Replacement
中的指定位置(或多个位置)。如果将 Replacement
作为 fun
给出,则会忽略此选项。
如果在 InsPos
中指定的任何位置 > 替换二进制的大小,则会引发 badarg
异常。
选项 global
和 {scope, part()}
的工作方式与 split/3
相同。返回类型始终为 binary/0
。
有关 Pattern
的说明,请参阅 compile_pattern/1
。
示例
1> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"X">>, []).
<<"aXcde">>
2> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"X">>, [global]).
<<"aXcXe">>
3> binary:replace(<<"abcde">>, <<"b">>, <<"[]">>, [{insert_replaced, 1}]).
<<"a[b]cde">>
4> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[]">>, [global, {insert_replaced, 1}]).
<<"a[b]c[d]e">>
5> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[]">>, [global, {insert_replaced, [1, 1]}]).
<<"a[bb]c[dd]e">>
6> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], <<"[-]">>, [global, {insert_replaced, [1, 2]}]).
<<"a[b-b]c[d-d]e">>
7> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], fun(M) -> <<$[, M/binary, $]>> end, []).
<<"a[b]cde">>
8> binary:replace(<<"abcde">>, [<<"b">>, <<"d">>], fun(M) -> <<$[, M/binary, $]>> end, [global]).
<<"a[b]c[d]e">>
-spec split(Subject, Pattern) -> Parts when Subject :: binary(), Pattern :: PatternBinary | [PatternBinary, ...] | cp(), PatternBinary :: nonempty_binary(), Parts :: [binary()].
-spec split(Subject, Pattern, Options) -> Parts when Subject :: binary(), Pattern :: PatternBinary | [PatternBinary, ...] | cp(), PatternBinary :: nonempty_binary(), Options :: [Option], Option :: {scope, part()} | trim | global | trim_all, Parts :: [binary()].
根据 Pattern
将 Subject
拆分为二进制数据列表。
如果未指定选项 global
,则只有 Pattern
在 Subject
中的第一次出现会导致拆分。
在结果中不包含在 Subject
中找到的 Pattern
的各个部分。
示例
1> binary:split(<<1,255,4,0,0,0,2,3>>, [<<0,0,0>>,<<2>>],[]).
[<<1,255,4>>, <<2,3>>]
2> binary:split(<<0,1,0,0,4,255,255,9>>, [<<0,0>>, <<255,255>>],[global]).
[<<0,1>>,<<4>>,<<9>>]
选项摘要
{scope, part()} - 工作方式与
match/3
和matches/3
相同。请注意,这仅定义了搜索匹配字符串的范围,它不会在拆分之前切割二进制文件。范围之前和之后的字节保留在结果中。请参阅下面的示例。trim - 删除结果中尾部的空部分(如
re:split/3
中的trim
一样)。trim_all - 删除结果中的所有空部分。
global - 重复拆分,直到
Subject
被耗尽。从概念上讲,选项global
使拆分在matches/3
返回的位置上工作,而通常它在match/3
返回的位置上工作。
在拆分之前,范围和将二进制拆开之间的差异示例
1> binary:split(<<"banana">>, [<<"a">>],[{scope,{2,3}}]).
[<<"ban">>,<<"na">>]
2> binary:split(binary:part(<<"banana">>,{2,3}), [<<"a">>],[]).
[<<"n">>,<<"n">>]
返回类型始终是一个二进制列表,其中所有二进制都引用 Subject
。这意味着 Subject
中的数据不会被复制到新的二进制文件中,并且在拆分结果不再被引用之前,Subject
不能被垃圾回收。
有关 Pattern
的说明,请参阅 compile_pattern/1
。