我遇到了一个奇怪的问题。 我有一个程序,它从外部源接收以字节为单位的数据,作为回报,我执行一些业务逻辑并发送回复。我们在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>>
仅因为utf8
和latin1
在间隔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^"