查看源代码 unicode (stdlib v6.2)
用于转换 Unicode 字符的函数。
此模块包含在不同字符表示之间进行转换的函数。它可以在 ISO Latin-1 字符和 Unicode 字符之间进行转换,但也可以在不同的 Unicode 编码(如 UTF-8、UTF-16 和 UTF-32)之间进行转换。
Erlang 二进制文件中的默认 Unicode 编码是 UTF-8,这也是 OTP 中内置函数和库期望找到二进制 Unicode 数据的格式。在列表中,Unicode 数据被编码为整数,每个整数表示一个字符,并简单地编码为该字符的 Unicode 代码点。
除表示代码点的整数或二进制文件中的 UTF-8 之外的其他 Unicode 编码称为“外部编码”。ISO Latin-1 编码在二进制文件和列表中称为 latin1 编码。
建议仅在与外部实体通信时才使用外部编码,如果这是必需的。在 Erlang/OTP 环境中工作时,建议在表示 Unicode 字符时将二进制文件保留为 UTF-8。ISO Latin-1 编码既支持向后兼容,也支持与不支持 Unicode 字符集的外部实体进行通信。
程序应始终以规范化形式操作,并将规范等效的 Unicode 字符视为相等。因此,所有字符应在系统边界上一次性规范化为一种形式。以下函数之一可以将字符转换为其规范化形式 characters_to_nfc_list/1
、characters_to_nfc_binary/1
、characters_to_nfd_list/1
或 characters_to_nfd_binary/1
。对于一般文本,首选 characters_to_nfc_list/1
或 characters_to_nfc_binary/1
,对于标识符,出于安全原因,首选兼容性规范化函数之一,例如 characters_to_nfkc_list/1
。规范化函数在 OTP 20 中引入。有关规范化的更多信息,请参阅 Unicode FAQ。
摘要
类型
一个 binary/0
,其中字符以用户指定的 UTF-8 以外的 Unicode 编码(即 UTF-16 或 UTF-32)进行编码。
一个 binary/0
,其中字符以 ISO Latin-1 编码。
一个 integer/0
,表示有效的 ISO Latin-1 字符 (0-255)。
一个 binary/0
,其中字符以 UTF-8 编码标准进行编码。
函数
检查二进制文件开头是否存在 UTF 字节顺序标记 (BOM)。
行为类似于 characters_to_list/2
,但生成的是二进制文件而不是 Unicode 列表。
将整数和二进制文件的可能深层列表转换为表示 Unicode 字符的整数列表。输入中的二进制文件可以具有以下编码之一的字符
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效组合字符的规范化形式。
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效组合字符的规范化形式。
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效分解字符的规范化形式。
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效分解字符的规范化形式。
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效组合字符的规范化形式。
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效组合字符的规范化形式。
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效分解字符的规范化形式。
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效分解字符的规范化形式。
从提供的 InEncoding
创建一个 UTF 字节顺序标记 (BOM) 作为二进制文件。
类型
-type chardata() :: charlist() | unicode_binary().
-type charlist() :: maybe_improper_list(char() | unicode_binary() | charlist(), unicode_binary() | []).
-type endian() :: big | little.
-type external_chardata() :: external_charlist() | external_unicode_binary().
-type external_charlist() :: maybe_improper_list(char() | external_unicode_binary() | external_charlist(), external_unicode_binary() | []).
-type external_unicode_binary() :: binary().
一个 binary/0
,其中字符以用户指定的 UTF-8 以外的 Unicode 编码(即 UTF-16 或 UTF-32)进行编码。
-type latin1_binary() :: binary().
一个 binary/0
,其中字符以 ISO Latin-1 编码。
-type latin1_char() :: byte().
一个 integer/0
,表示有效的 ISO Latin-1 字符 (0-255)。
-type latin1_chardata() :: latin1_charlist() | latin1_binary().
等效于 iodata/0
。
-type latin1_charlist() :: maybe_improper_list(latin1_char() | latin1_binary() | latin1_charlist(), latin1_binary() | []).
等效于 iolist/0
。
-type unicode_binary() :: binary().
一个 binary/0
,其中字符以 UTF-8 编码标准进行编码。
函数
-spec bom_to_encoding(Bin) -> {Encoding, Length} when Bin :: binary(), Encoding :: latin1 | utf8 | {utf16, endian()} | {utf32, endian()}, Length :: non_neg_integer().
检查二进制文件开头是否存在 UTF 字节顺序标记 (BOM)。
如果提供的二进制文件 Bin
以 UTF-8、UTF-16 或 UTF-32 的有效 BOM 开头,则该函数将返回识别的编码以及 BOM 的长度(以字节为单位)。
如果未找到 BOM,则该函数返回 {latin1,0}
。
-spec characters_to_binary(Data) -> Result when Data :: latin1_chardata() | chardata() | external_chardata(), Result :: binary() | {error, binary(), RestData} | {incomplete, binary(), binary()}, RestData :: latin1_chardata() | chardata() | external_chardata().
-spec characters_to_binary(Data, InEncoding) -> Result when Data :: latin1_chardata() | chardata() | external_chardata(), InEncoding :: encoding(), Result :: binary() | {error, binary(), RestData} | {incomplete, binary(), binary()}, RestData :: latin1_chardata() | chardata() | external_chardata().
-spec characters_to_binary(Data, InEncoding, OutEncoding) -> Result when Data :: latin1_chardata() | chardata() | external_chardata(), InEncoding :: encoding(), OutEncoding :: encoding(), Result :: binary() | {error, binary(), RestData} | {incomplete, binary(), binary()}, RestData :: latin1_chardata() | chardata() | external_chardata().
行为类似于 characters_to_list/2
,但生成的是二进制文件而不是 Unicode 列表。
InEncoding
定义了如果 Data
中存在二进制文件,则如何解释输入
OutEncoding
定义了将生成什么格式的输出。
选项
unicode
-utf8
的别名,因为这是二进制文件中 Unicode 字符的首选编码。utf16
-{utf16,big}
的别名。utf32
-{utf32,big}
的别名。
原子 big
和 little
表示大端或小端编码。
错误和异常的发生方式与 characters_to_list/2
中相同,但元组 error
或 incomplete
中的第二个元素是一个 binary/0
,而不是 list/0
。
-spec characters_to_list(Data) -> Result when Data :: latin1_chardata() | chardata() | external_chardata(), Result :: string() | {error, string(), RestData} | {incomplete, string(), binary()}, RestData :: latin1_chardata() | chardata() | external_chardata().
-spec characters_to_list(Data, InEncoding) -> Result when Data :: latin1_chardata() | chardata() | external_chardata(), InEncoding :: encoding(), Result :: string() | {error, string(), RestData} | {incomplete, string(), binary()}, RestData :: latin1_chardata() | chardata() | external_chardata().
将整数和二进制文件的可能深层列表转换为表示 Unicode 字符的整数列表。输入中的二进制文件可以具有以下编码之一的字符
- ISO Latin-1(0-255,每个字节一个字符)。此处,大小写参数
InEncoding
应指定为latin1
。 - UTF 编码之一,指定为参数
InEncoding
。
请注意,列表中的整数始终表示代码点,而不管传递的 InEncoding
如何。如果传递 InEncoding latin1
,则只允许代码点 < 256;否则,允许所有有效的 Unicode 代码点。
如果 InEncoding
为 latin1
,则参数 Data
对应于 iodata/0
类型,但对于 unicode
,参数 Data
可以包含 > 255 的整数(超出 ISO Latin-1 范围的 Unicode 字符),这使其作为 iodata/0
无效。
该函数的主要目的是将 Unicode 字符的组合转换为纯 Unicode 字符串(列表表示形式),以便进一步处理。对于将数据写入外部实体,反向函数 characters_to_binary/3
非常方便。
选项 unicode
是 utf8
的别名,因为这是二进制文件中 Unicode 字符的首选编码。utf16
是 {utf16,big}
的别名,utf32
是 {utf32,big}
的别名。原子 big
和 little
表示大端或小端编码。
如果无法转换数据,可能是因为列表中存在非法的 Unicode/ISO Latin-1 字符,或者因为任何二进制文件中存在无效的 UTF 编码,则会返回错误元组。错误元组包含标记 error
、一个列表(表示在发生错误之前可以转换的字符)以及一个表示(包括错误整数/字节之后)的字符。最后一部分主要用于调试,因为它仍然构成一个可能较深或混合的列表,或者两者兼而有之,深度不一定与原始数据相同。当遍历列表时会发生错误,并且将未解码的内容“按原样”返回。
但是,如果输入 Data
是纯二进制文件,则保证错误元组的第三部分也是二进制文件。
发生错误的原因如下
超出范围的整数。
如果
InEncoding
为latin1
,则只要在列表中找到 > 255 的整数,就会发生错误。如果
InEncoding
属于 Unicode 类型,则只要找到以下任一情况,就会发生错误- 大于 16#10FFFF(最大 Unicode 字符)的整数
- 范围为 16#D800 到 16#DFFF 的整数(为 UTF-16 代理对保留的无效范围)
不正确的 UTF 编码。
如果
InEncoding
是 UTF 类型之一,则任何二进制文件中的字节在该编码中必须有效。可能由于以下各种原因而发生错误
- “纯”解码错误(如字节的高位错误)。
- 字节被解码为一个太大的数字。
- 字节被解码为无效 Unicode 范围内的代码点。
- 编码“过长”,意味着一个数字应该使用更少的字节进行编码。
会特殊处理截断的 UTF 情况,请参见下面有关不完整二进制文件的段落。
如果
InEncoding
为latin1
,则只要二进制文件包含完整的字节,二进制文件始终有效,因为每个字节都属于有效的 ISO Latin-1 范围。
一种特殊的错误是,当没有找到实际无效的整数或字节时,但尾部的 binary/0
包含的字节太少,无法解码最后一个字符。如果从文件中分块读取字节,或者二进制文件以其他方式在非 UTF 字符边界上分割,则可能会发生此错误。此时会返回一个 incomplete
元组,而不是 error
元组。它与 error
元组具有相同的部分,但标签是 incomplete
而不是 error
,并且最后一个元素始终保证是一个二进制数据,该二进制数据由(到目前为止)有效的 UTF 字符的第一部分组成。
如果一个 UTF 字符在 Data
中的两个连续二进制数据上分割,则转换成功。这意味着只要整个范围被指定为输入,且不发生错误,就可以从一系列二进制数据中解码一个字符。
示例
decode_data(Data) ->
case unicode:characters_to_list(Data,unicode) of
{incomplete,Encoded, Rest} ->
More = get_some_more_data(),
Encoded ++ decode_data([Rest, More]);
{error,Encoded,Rest} ->
handle_error(Encoded,Rest);
List ->
List
end.
但是,不允许使用非完整字节的位串,因此 UTF 字符必须沿 8 位边界分割才能被解码。
在以下情况下会抛出 badarg
异常
- 任何参数类型错误。
- 列表结构无效(尾部为数字)。
- 二进制数据不包含完整字节(位串)。
-spec characters_to_nfc_binary(chardata()) -> unicode_binary() | {error, unicode_binary(), chardata()}.
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效组合字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个 utf8 编码的二进制数据。
4> unicode:characters_to_nfc_binary([<<"abc..a">>,[778],$a,[776],$o,[776]]).
<<"abc..åäö"/utf8>>
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效组合字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个字符列表。
3> unicode:characters_to_nfc_list([<<"abc..a">>,[778],$a,[776],$o,[776]]).
"abc..åäö"
-spec characters_to_nfd_binary(chardata()) -> unicode_binary() | {error, unicode_binary(), chardata()}.
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效分解字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个 utf8 编码的二进制数据。
2> unicode:characters_to_nfd_binary("abc..åäö").
<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>>
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为规范等效分解字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个字符列表。
1> unicode:characters_to_nfd_list("abc..åäö").
[97,98,99,46,46,97,778,97,776,111,776]
-spec characters_to_nfkc_binary(chardata()) -> unicode_binary() | {error, unicode_binary(), chardata()}.
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效组合字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个 utf8 编码的二进制数据。
4> unicode:characters_to_nfkc_binary([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
<<"abc..åäö32"/utf8>>
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效组合字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个字符列表。
3> unicode:characters_to_nfkc_list([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
"abc..åäö32"
-spec characters_to_nfkd_binary(chardata()) -> unicode_binary() | {error, unicode_binary(), chardata()}.
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效分解字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个 utf8 编码的二进制数据。
2> unicode:characters_to_nfkd_binary(["abc..åäö",[65299,65298]]).
<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>>
根据 Unicode 标准,将字符和二进制文件的可能深层列表转换为兼容等效分解字符的规范化形式。
输入中的任何二进制数据都必须使用 utf8 编码。
结果是一个字符列表。
1> unicode:characters_to_nfkd_list(["abc..åäö",[65299,65298]]).
[97,98,99,46,46,97,778,97,776,111,776,51,50]
从提供的 InEncoding
创建一个 UTF 字节顺序标记 (BOM) 作为二进制文件。
如果支持 BOM,则它应该位于 UTF 编码文件或消息的开头。
该函数对于 latin1
编码返回 <<>>
,因为 ISO Latin-1 没有 BOM。
请注意,UTF-8 的 BOM 很少使用,它实际上不是字节顺序标记。UTF-8 显然不存在字节顺序问题,因此 BOM 仅用于区分 UTF-8 编码和其他 UTF 格式。