转换 UTF-8 iso-8859 字节 - String.to_charlist



我遇到了一个奇怪的问题。 我有一个程序,它从外部源接收以字节为单位的数据,作为回报,我执行一些业务逻辑并发送回复。我们在String.to_charlist上遇到了一个奇怪的问题。

在 iex 中试试这个:

String.to_charlist <<169, 99, 111, 114, 94, 51, 94, 51, 94, 66, 52, 57, 49, 49, 49, 32, 32, 49, 48, 51, 53, 94, 67, 79, 77, 80, 76, 69, 84, 69, 68, 94, 49, 49, 52, 50, 52, 53, 94, 75>>

这将引发以下错误:

** (UnicodeConversionError) invalid encoding starting at <<169, 99, 111, 114, 94, 51, 94, 51, 94, 66, 52, 57, 49, 49, 49, 32, 32, 49, 48, 51, 53, 94, 67, 79, 77, 80, 76, 69, 84, 69, 68, 94, 49, 49, 52, 50, 52, 53, 94, 75>>
(elixir) lib/string.ex:2035: String.to_charlist/1

现在,如果您去掉第一个字节并依次尝试:

String.to_charlist <<99, 111, 114, 94, 51, 94, 51, 94, 66, 52, 57, 49, 49, 49, 32, 32, 49, 48, 51, 53, 94, 67, 79, 77, 80, 76, 69, 84, 69, 68, 94, 49, 49, 52, 50, 52, 53, 94, 75>>

你会得到:

'cor^3^3^B49111 1035^COMPLETE^114245^K'

有没有其他方法将这些字节转换为字符串?我知道像 169 这样的某些字符可能无法显示,但推荐的处理方式是什么?

感谢您的帮助。

我确实找到了这个:

<<169 :: utf8, 0>> 

返回 <<194, 169, 0>> 添加 194。因此,如果您将其粘贴到 iex 中,则输出似乎是正确的。

<<194, 169, 99, 111, 114, 94, 51, 94, 51, 94, 66, 52, 57, 49, 49, 49, 32, 32, 49, 48, 51, 53, 94, 67, 79, 77, 80, 76, 69, 84, 69, 68, 94, 49, 49, 52, 50, 52, 53, 94, 75>> 

我是否需要编写一个函数来循环遍历字节并调用<>然后减少返回的字节数(0 concat 除外)?

String.to_charlist/1首先是多余的:

String.to_charlist <<99, 111, 114, 94, 51, 94, 51, 94>>

仅因为utf8latin1在间隔1–127中共享相同的代码点。以下内容足以获得完全有效的二进制文件:

<<99, 111, 114, 94, 51, 94, 51, 94>>
#⇒ "cor^3^3^"

不幸的是,您收到的不是utf8编码,Elixir没有内置工具来在编码之间转换二进制文件。您不能只是删除有意义的符号。

我建议使用codepagex包进行转换:

Codepagex.from_string(<<99, 111, 114, 94, 51, 94, 51, 94>>, :iso_8859_1)
#⇒ "cor^3^3^"

另一种方法是使用 erlang 的unicode.characters_to_binary/2

:unicode.characters_to_binary(
<<169, 99, 111, 114, 94, 51, 94, 51, 94>>, :latin1, :utf8
)
#⇒ "©cor^3^3^"

另一种使用Kernel.SpecialForms.for/1理解的解决方案:

to_string(for <<c :: 8 <- <<169, 99, 111, 114, 94, 51, 94, 51, 94>> >>, do: c)
#⇒ "©cor^3^3^"

最新更新