破坏utf8转换?

时间:2015-05-05 08:40:18

标签: erlang

我试图像这样强制使用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,因此这应该与以前相同。

我忽略了什么吗?

谢谢:)

1 个答案:

答案 0 :(得分: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("œ").