非常教程

Erlang 20参考手册

stdlib

unicode

模块

unicode(字符集)

模块摘要

用于转换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/1characters_to_nfc_binary/1characters_to_nfd_list/1characters_to_nfd_binary/1。对于一般文本characters_to_nfc_list/1或者characters_to_nfc_binary/1是优选的,并且对于标识符来说characters_to_nfkc_list/1,由于安全原因,其中一个兼容性标准化函数例如是优选的。在OTP 20中引入的规范化函数。有关规范化的更多信息,请参阅Unicode FAQ

数据类型

encoding() =

    latin1 |

    unicode |

    utf8 |

    utf16 |

    {utf16, endian()} |

    utf32 |

    {utf32, endian()}

endian() = big | little

unicode_binary() = binary()

binary()使用UTF-8编码标准编码的字符。

chardata() = charlist() | unicode_binary()

charlist() =

    maybe_improper_list(char() | unicode_binary() | charlist(),

unicode_binary() | [])

external_unicode_binary() = binary()

binary()以UTF-8以外的用户指定的Unicode编码(即UTF-16或UTF-32)编码的字符。

external_chardata() =

external_charlist() | external_unicode_binary()

external_charlist() =

    maybe_improper_list(char() |

external_unicode_binary() |

external_charlist(),

external_unicode_binary() | [])

latin1_binary() = binary()

binary()带有ISO Latin-1编码的字符。

latin1_char() = byte()

一个表示有效的ISO Latin-1字符(0-255)的整数()。

latin1_chardata() = latin1_charlist() | latin1_binary()

类似于iodata()

latin1_charlist() =

    maybe_improper_list(latin1_char() |

latin1_binary() |

latin1_charlist(),

latin1_binary() | [])

类似于iolist().

输出

bom_to_encoding(Bin) -> {Encoding, Length}

类型

binary()byte_size(Bin) >= 4

在二进制文件的开头检查UTF字节顺序标记(BOM)。如果提供的二进制文件Bin以UTF-8,UTF-16或UTF-32的有效BOM表开头,则该函数返回标识的编码以及BOM长度(以字节为单位)。

如果找不到BOM,则函数返回{latin1,0}

characters_to_binary(Data) -> Result

类型

类似于characters_to_binary(Data, unicode, unicode).

characters_to_binary(Data, InEncoding) -> Result

类型

类似于characters_to_binary(Data, InEncoding, unicode)

characters_to_binary(Data, InEncoding, OutEncoding) -> Result

类型

表现为characters_to_list/2,但产生一个二进制代替Unicode列表。

InEncoding定义了如何在数据中存在二进制文件时解释输入

OutEncoding 定义将以什么格式生成输出。

选项:

unicode

一个别名utf8,因为这是二进制文件中Unicode字符的首选编码。

utf16

别名{utf16,big}

utf32

别名{utf32,big}

原子biglittle表示大端或小端编码。

错误和异常发生在中characters_to_list/2,但元组中的第二个元素error或者incompletebinary()而不是 list()

characters_to_list(Data) -> Result

类型

类似于characters_to_list(Data, unicode)

characters_to_list(Data, InEncoding) -> Result

类型

将可能较深的整数和二进制列表转换为表示Unicode字符的整数列表。输入中的二进制文件可以将字符编码为以下之一:

  • ISO Latin-1(0-255,每字节一个字符)。这里,case参数InEncoding被指定为latin1
  • UTF编码之一,它被指定为参数InEncoding

只有当InEncoding其中一个UTF编码时,列表中的整数才允许大于255。

如果InEncoding为latin1,则参数Data对应于iodata()类型,但对于unicode,参数Data可以包含整数> 255(超出ISO Latin-1范围的Unicode字符),这使得它与iodata()无效。

该函数的目的主要是将Unicode字符的组合转换为列表表示中的纯Unicode字符串以供进一步处理。为了将数据写入外部实体,反向功能characters_to_binary/3派上用场。

选项unicode是utf8的别名,因为这是二进制文件中Unicode字符的首选编码。 utf16是{utf16,big}的别名,utf32是{utf32,big}的别名。 大小的原子表示大端或小端编码。

如果由于列表中存在非法的Unicode / ISO Latin-1字符或由于任何二进制文件中的UTF编码无效导致无法转换数据,则会返回错误元组。错误元组包含标签error,一个表示在错误发生前可以转换的字符的列表,以及包含和出现在有问题的整数/字节后的字符表示。最后一部分主要用于调试,因为它仍然构成可能深度或混合列表,或者两者都有,不一定与原始数据具有相同的深度。遍历列表时发生错误,并且按原样返回解码的内容。

但是,如果输入Data是纯二进制,则错误元组的第三部分也保证为二进制。

出现以下原因会导致错误:

  • 整数超出范围。如果InEncodinglatin1,只要在列表中找到大于255的整数,就会发生错误。如果InEncoding是Unicode类型,则只要发现以下任一情况就会发生错误:
-  An integer > 16#10FFFF (the maximum Unicode character)
-  An integer in the range 16#D800 to 16#DFFF (invalid range reserved for UTF-16 surrogate pairs)
  • 不正确的UTF编码。如果InEncoding是UTF类型之一,则任何二进制文件中的字节必须在该编码中有效。出于各种原因可能会出现错误,包括以下情况:
-  "Pure" decoding errors (like the upper bits of the bytes being wrong).
-  The bytes are decoded to a too large number.
-  The bytes are decoded to a code point in the invalid Unicode range.
-  Encoding is "overlong", meaning that a number should have been encoded in fewer bytes.

截断UTF的情况会特别处理,请参阅下面有关不完整二进制文件的段落。

如果InEncodinglatin1,则只要包含整个字节,二进制文件就始终有效,因为每个字节都落入有效的ISO Latin-1范围。

一种特殊类型的错误是当没有找到实际的无效整数或字节时,但是后缀二进制()包含太少字节来解码最后一个字符。 如果从块中的文件中读取字节,或者如果其他方式的二进制文件在非UTF字符边界上被分割,则会发生此错误。 然后返回一个不完整的元组,而不是错误元组。 它由与错误元组相同的部分组成,但标记是不完整的而不是错误的,最后一个元素总是保证是一个由(至今)有效的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异常被抛出以下情况:

  • 任何参数的类型都是错误的。
  • 列表结构无效(尾数为数字)。
  • 二进制文件不包含整个字节(位串)。

characters_to_nfc_list(CD :: chardata()) ->

char() | {error, char(), chardata()}

根据Unicode标准,将可能深层的字符和二进制文件转换为规范化的等同组合字符的规范化形式。

输入中的任何二进制文件都必须使用utf8编码进行编码。

结果是一个字符列表。

3> unicode:characters_to_nfc_list([<<"abc..a">>,[778],$a,[776],$o,[776]]).
"abc..åäö"

characters_to_nfc_binary(CD :: 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>>

characters_to_nfd_list(CD :: chardata()) ->

char() | {error, char(), chardata()}

根据Unicode标准,将可能深层的字符和二进制文件转换为规范化等效分解字符的规范化形式。

输入中的任何二进制文件都必须使用utf8编码进行编码。

结果是一个字符列表。

1> unicode:characters_to_nfd_list("abc..åäö").
[97,98,99,46,46,97,778,97,776,111,776]

characters_to_nfd_binary(CD :: 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>>

characters_to_nfkc_list(CD :: chardata()) ->

char() |

{error, char(), chardata()}

根据Unicode标准,将可能深层的字符和二进制文件转换为兼容的Compose字符的规范化形式。

输入中的任何二进制文件都必须使用utf8编码进行编码。

结果是一个字符列表。

3> unicode:characters_to_nfkc_list([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
"abc..åäö32"

characters_to_nfkc_binary(CD :: chardata()) ->

unicode_binary() |

{error, unicode_binary(), chardata()}

根据Unicode标准,将可能深层的字符和二进制文件转换为兼容的Compose字符的规范化形式。

输入中的任何二进制文件都必须使用utf8编码进行编码。

结果是一个utf8编码二进制。

4> unicode:characters_to_nfkc_binary([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
<<"abc..åäö32"/utf8>>

characters_to_nfkd_list(CD :: chardata()) ->

char() |

{error, char(), chardata()}

根据Unicode标准,将可能深层的字符和二进制文件转换为兼容的分解字符的规范化形式。

输入中的任何二进制文件都必须使用utf8编码进行编码。

结果是一个字符列表。

1> unicode:characters_to_nfkd_list(["abc..åäö",[65299,65298]]).
[97,98,99,46,46,97,778,97,776,111,776,51,50]

characters_to_nfkd_binary(CD :: 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>>

encoding_to_bom(InEncoding) -> Bin

类型

一个binary()byte_size(Bin) >= 4

从提供的二进制文件创建UTF字节顺序标记(BOM)InEncoding。如果支持BOM,预计将首先放置在UTF编码的文件或消息中。

该函数返回<<>>latin1编码,因为是ISO Latin-1的没有BOM。

请注意,UTF-8的BOM很少使用,它实际上不是字节顺序标记。UTF-8显然没有字节顺序问题,因此BOM仅用于区分UTF-8编码和其他UTF格式。

Erlang 20

Erlang 是一种通用的面向并发的编程语言,可应付大规模开发活动的程序设计语言和运行环境。

主页 https://www.erlang.org/
源码 https://github.com/erlang/otp
版本 20
发布版本 20.1