我遇到了一个奇怪的问题。我有一个程序可以从外部源接收以字节为单位的数据,作为回报,我可以执行一些业务逻辑并发送回复。我们在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 ^ COMPLETED ^ 114245 ^ K'
我应该以其他方式将这些字节转换为字符串吗?我了解某些字符(例如169)可能无法显示,但是推荐的处理方式是什么?
感谢您的帮助。
我确实找到了:
<<169 :: utf8, 0>>
返回添加了194的<< 194、169、0 >>。因此,如果将其粘贴到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除外)?
答案 0 :(得分:1)
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^"