查看源代码 binary (stdlib v6.2)

用于处理二进制数据的库。

此模块包含用于操作面向字节的二进制数据的函数。尽管大多数函数可以使用位语法提供,但此库中的函数经过高度优化,预计比用纯 Erlang 编写的对应函数执行速度更快或消耗更少的内存,或两者兼而有之。

该模块根据 Erlang 增强提案 (EEP) 31 提供。

注意

该库处理面向字节的数据。对于非二进制(不包含完整的八位字节)的位串,此模块中的任何函数都会抛出 badarg 异常。

概要

类型

表示已编译搜索模式的不透明数据类型。

二进制数据中的一部分(或范围)的表示。Startbinary/0 中基于零的偏移量,Length 是该部分的长度。

函数

以整数形式返回二进制 Subject 中位置 Pos (基于零) 处的字节。

Subject 转换为 byte/0 的列表,每个 byte/0 表示一个字节的值。

Subject 转换为 byte/0 的列表,每个 byte/0 表示一个字节的值。PosLen 或可选的 PosLen 表示要转换的 Subject 二进制数据的哪一部分。默认情况下,将转换整个 Subject 二进制数据。

构建表示搜索模式编译的内部结构,该结构稍后将在函数 match/3matches/3split/3replace/4 中使用。

创建一个二进制数据,其中包含 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) 的结果,构造新的二进制数据。

根据 PatternSubject 拆分为二进制数据列表。

类型

-opaque cp()

表示已编译搜索模式的不透明数据类型。

保证是 tuple/0,以允许程序将其与未预编译的搜索模式区分开。

链接到此类型

part()

查看源代码 (自 OTP R14B 起)
-type part() :: {Start :: non_neg_integer(), Length :: integer()}.

二进制数据中的一部分(或范围)的表示。Startbinary/0 中基于零的偏移量,Length 是该部分的长度。

作为此模块中函数的输入,允许使用反向部分规范(使用负 Length 构造),以便二进制数据的一部分从 Start + Length 开始,长度为 -Length。这对于将二进制数据的最后 N 个字节引用为 {size(Binary), -N} 非常有用。此模块中的函数始终返回具有正 Lengthpart/0

函数

链接到此函数

at(Subject, Pos)

查看源代码 (自 OTP R14B 起)
-spec at(Subject, Pos) -> byte() when Subject :: binary(), Pos :: non_neg_integer().

以整数形式返回二进制 Subject 中位置 Pos (基于零) 处的字节。

如果 Pos >= byte_size(Subject),则会引发 badarg 异常。

链接到此函数

bin_to_list(Subject)

查看源代码 (自 OTP R14B 起)
-spec bin_to_list(Subject) -> [byte()] when Subject :: binary().

Subject 转换为 byte/0 的列表,每个 byte/0 表示一个字节的值。

示例

1> binary:bin_to_list(<<"erlang">>).
"erlang"
%% or [101,114,108,97,110,103] in list notation.
链接到此函数

bin_to_list(Subject, PosLen)

查看源代码 (自 OTP R14B 起)
-spec bin_to_list(Subject, PosLen) -> [byte()] when Subject :: binary(), PosLen :: part().

等效于 bin_to_list(Subject, Pos, Len)

链接到此函数

bin_to_list(Subject, Pos, Len)

查看源代码 (自 OTP R14B 起)
-spec bin_to_list(Subject, Pos, Len) -> [byte()]
                     when Subject :: binary(), Pos :: non_neg_integer(), Len :: integer().

Subject 转换为 byte/0 的列表,每个 byte/0 表示一个字节的值。PosLen 或可选的 PosLen 表示要转换的 Subject 二进制数据的哪一部分。默认情况下,将转换整个 Subject 二进制数据。

示例

1> binary:bin_to_list(<<"erlang">>, {1,3}).
"rla"
%% or [114,108,97] in list notation.

如果 PosLen 或可选的 PosLen 以任何方式引用二进制数据外部,则会引发 badarg 异常。

链接到此函数

compile_pattern(Pattern)

查看源代码 (自 OTP R14B 起)
-spec compile_pattern(Pattern) -> cp()
                         when
                             Pattern :: PatternBinary | [PatternBinary, ...],
                             PatternBinary :: nonempty_binary().

构建表示搜索模式编译的内部结构,该结构稍后将在函数 match/3matches/3split/3replace/4 中使用。

返回的 cp/0 保证是 tuple/0,以允许程序将其与未预编译的搜索模式区分开。

指定二进制数据列表时,它表示要搜索的一组替代二进制数据。例如,如果将 [<<"functional">>,<<"programming">>] 指定为 Pattern,这意味着 <<"functional">><<"programming">>"。模式是一组替代方案;当仅指定单个二进制数据时,该组只有一个元素。模式中替代方案的顺序并不重要。

用于搜索替代方案的二进制数据列表必须是扁平的、合适的且非空的。

如果 Pattern 不是二进制数据或长度 > 0 的扁平的合适非空二进制数据列表,则会引发 badarg 异常。

链接到此函数

copy(Subject)

查看源代码 (自 OTP R14B 起)
-spec copy(Subject) -> binary() when Subject :: binary().

等效于 copy(Subject, 1)

链接到此函数

copy(Subject, N)

查看源代码 (自 OTP R14B 起)
-spec copy(Subject, N) -> binary() when Subject :: binary(), N :: non_neg_integer().

创建一个二进制数据,其中包含 Subject 的内容,并重复 N 次。

即使 N = 1,此函数始终会创建新的二进制数据。通过对引用较大二进制数据的二进制数据使用 copy/1,可以释放较大的二进制数据以进行垃圾回收。

注意

通过故意复制单个二进制数据以避免引用较大的二进制数据,可以创建比所需更多的二进制数据,而不是释放较大的二进制数据以供后续垃圾回收。共享二进制数据通常很好。只有在特殊情况下,当小部分引用大的二进制数据并且大的二进制数据不再在任何进程中使用时,故意复制才是一个好主意。

链接到此函数

decode_hex(Bin)

查看源代码 (自 OTP 24.0 起)
-spec decode_hex(Bin) -> Bin2 when Bin :: <<_:_*16>>, Bin2 :: binary().

将十六进制编码的二进制数据解码为二进制数据。

示例

1> binary:decode_hex(<<"66">>).
<<"f">>
链接到此函数

decode_unsigned(Subject)

查看源码 (自 OTP R14B 起)
-spec decode_unsigned(Subject) -> Unsigned when Subject :: binary(), Unsigned :: non_neg_integer().

等效于 decode_unsigned(Subject, big)

链接到此函数

decode_unsigned(Subject, Endianness)

查看源码 (自 OTP R14B 起)
-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
链接到此函数

encode_hex(Bin)

查看源码 (自 OTP 24.0 起)
-spec encode_hex(Bin) -> Bin2 when Bin :: binary(), Bin2 :: <<_:_*16>>.

等效于 encode_hex(Bin, uppercase)

链接到此函数

encode_hex(Bin, Case)

查看源码 (自 OTP 26.0 起)
-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">>
链接到此函数

encode_unsigned(Unsigned)

查看源码 (自 OTP R14B 起)
-spec encode_unsigned(Unsigned) -> binary() when Unsigned :: non_neg_integer().

等效于 encode_unsigned(Unsigned, big)

链接到此函数

encode_unsigned(Unsigned, Endianness)

查看源码 (自 OTP R14B 起)
-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>>
链接到此函数

first(Subject)

查看源码 (自 OTP R14B 起)
-spec first(Subject) -> byte() when Subject :: binary().

以整数形式返回二进制 Subject 的第一个字节。如果 Subject 的大小为零,则会引发 badarg 异常。

链接到此函数

last(Subject)

查看源码 (自 OTP R14B 起)
-spec last(Subject) -> byte() when Subject :: binary().

以整数形式返回二进制 Subject 的最后一个字节。如果 Subject 的大小为零,则会引发 badarg 异常。

链接到此函数

list_to_bin(ByteList)

查看源码 (自 OTP R14B 起)
-spec list_to_bin(ByteList) -> binary() when ByteList :: iolist().

其作用与 erlang:list_to_binary/1 完全相同,为了完整性而添加。

链接到此函数

longest_common_prefix(Binaries)

查看源码 (自 OTP R14B 起)
-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 异常。

链接到此函数

longest_common_suffix(Binaries)

查看源码 (自 OTP R14B 起)
-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 异常。

链接到此函数

match(Subject, Pattern)

查看源码 (自 OTP R14B 起)
-spec match(Subject, Pattern) -> Found | nomatch
               when
                   Subject :: binary(),
                   Pattern :: PatternBinary | [PatternBinary, ...] | cp(),
                   PatternBinary :: nonempty_binary(),
                   Found :: part().

等效于 match(Subject, Pattern, [])

链接到此函数

match(Subject, Pattern, Options)

查看源码 (自 OTP R14B 起)
-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 异常。

链接到此函数

matches(Subject, Pattern)

查看源码 (自 OTP R14B 起)
-spec matches(Subject, Pattern) -> Found
                 when
                     Subject :: binary(),
                     Pattern :: PatternBinary | [PatternBinary, ...] | cp(),
                     PatternBinary :: nonempty_binary(),
                     Found :: [part()].

等效于 matches(Subject, Pattern, [])

链接到此函数

matches(Subject, Pattern, Options)

查看源码 (自 OTP R14B 起)
-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 异常。

链接到此函数

part(Subject, PosLen)

查看源码 (自 OTP R14B 起)
-spec part(Subject, PosLen) -> binary() when Subject :: binary(), PosLen :: part().

等效于 part(Subject, Pos, Len)

链接到此函数

part(Subject, Pos, Len)

查看源码 (自 OTP R14B 起)
-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/2part/3 也可在 erlang 模块中以 binary_part/2binary_part/3 的名称使用。这些 BIF 允许在 guard 测试中使用。

如果 PosLen 以任何方式引用二进制外部,则会引发 badarg 异常。

链接到此函数

referenced_byte_size(Binary)

查看源码 (自 OTP R14B 起)
-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

注意

二进制数据在进程之间共享。如果另一个进程仍然引用较大的二进制,则复制此进程使用的部分只会消耗更多内存,并且不会释放较大的二进制以进行垃圾回收。请极其谨慎地使用此类侵入性函数,并且仅在检测到实际问题时才使用。

链接到此函数

replace(Subject, Pattern, Replacement)

查看源码 (自 OTP R14B 起)
-spec replace(Subject, Pattern, Replacement) -> Result
                 when
                     Subject :: binary(),
                     Pattern :: PatternBinary | [PatternBinary, ...] | cp(),
                     PatternBinary :: nonempty_binary(),
                     Replacement :: binary() | fun((binary()) -> binary()),
                     Result :: binary().

等效于 replace(Subject, Pattern, Replacement, [])

链接到此函数

replace(Subject, Pattern, Replacement, Options)

查看源码 (自 OTP R14B 起)
-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">>
链接到此函数

split(Subject, Pattern)

查看源码 (自 OTP R14B 起)
-spec split(Subject, Pattern) -> Parts
               when
                   Subject :: binary(),
                   Pattern :: PatternBinary | [PatternBinary, ...] | cp(),
                   PatternBinary :: nonempty_binary(),
                   Parts :: [binary()].

等效于 split(Subject, Pattern, [])

链接到此函数

split(Subject, Pattern, Options)

查看源码 (自 OTP R14B 起)
-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()].

根据 PatternSubject 拆分为二进制数据列表。

如果未指定选项 global,则只有 PatternSubject 中的第一次出现会导致拆分。

在结果中不包含在 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/3matches/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