损坏的 utf8 转换?

Broken utf8 conversion?

我正在尝试像这样强制使用 UTF-8:

to_utf8(X) when is_list(X) ->
    unicode:characters_to_binary(X, utf8);
to_utf8(X) when is_binary(X) ->
    to_utf8(binary_to_list(X));
to_utf8(X) -> X.

并像这样测试它:

<<"é"/utf8>> = to_utf8(<<"é">>),
<<"Ø"/utf8>> = to_utf8(<<"Ø">>),
<<"œ"/utf8>> = to_utf8(<<"œ">>),

使用 R16B03 时一切正常。然而,升级到 Erlang 17.5 后,该函数不再适用于像“-”或“-”这样的字符,即使它们在 UTF-8 中可用

由于 R17 使用 utf-8 作为默认编码而不是 R16 的 latin-1,因此这应该与以前一样工作。

我是不是忽略了什么?

谢谢:)

我将在下面的示例中使用 œ 作为示例 unicode 字符:

<<197,147>>         = <<"œ"/utf8>>.
[197,147]           = binary_to_list(<<"œ"/utf8>>).
<<195,133,194,147>> = unicode:characters_to_binary(binary_to_list(<<"œ"/utf8>>), utf8).

在 R17 之前,latin1 的默认编码允许它与 binary_to_list/1 结合使用。新的默认值是 unicode.

列表 [197,147] 不是 unicode:characters_to_binary/2 中隐含输出编码 unicode 所期望的格式。如果我们想使用 binary_to_list/1,我们必须指定输出编码应该是 latin1 作为 R16 及以下的默认值:

<<197,147>> = unicode:characters_to_binary(binary_to_list(<<"œ"/utf8>>), latin1, latin1).

另一个解决方案是使用 unicode:characters_to_list/1 而不是 binary_to_string:

[339]       = unicode:characters_to_list(<<"œ"/utf8>>).
<<197,147>> = unicode:characters_to_binary(unicode:characters_to_list(<<"œ"/utf8>>), utf8).

更好的解决方案是直接使用 unicode:characters_to_binary/1,2,3,因为不需要将二进制文件转换为列表:

<<"œ"/utf8>> = unicode:characters_to_binary(<<197,147>>).
<<"œ"/utf8>> = unicode:characters_to_binary("œ").