2016-09-29 26 views
2

给定一个药剂位串在UTF-16LE编码:转换一个UTF-16LE药剂比特串到药剂字符串

<<68, 0, 101, 0, 118, 0, 97, 0, 115, 0, 116, 0, 97, 0, 116, 0, 111, 0, 114, 0, 0, 0>> 

怎样可以得到这个转换成可读的药剂字符串(它阐述了“破坏者”) ?我得到的最接近的是将上面的代码转换为Unicode代码点列表(["0044", "0065", ...])并试图将\u转义序列预先添加到它们中,但Elixir由于它是无效序列而引发错误。我没有想法。

+0

你”已经[回答](http://stackoverflow.com/a/39601246/3102718)这个问题,不是吗? –

+0

这是一个暂时的黑客攻击,对于更复杂的情况,例如解析由空字节终止的未知长度的字符串,这是不够的。 – user701847

+0

好的,谢谢,只是好奇。 –

回答

5

最简单的方法是使用从:unicode模块功能:

:unicode.characters_to_binary(utf16binary, {:utf16, :little}) 

例如

<<68, 0, 101, 0, 118, 0, 97, 0, 115, 0, 116, 0, 97, 0, 116, 0, 111, 0, 114, 0, 0, 0>> 
|> :unicode.characters_to_binary({:utf16, :little}) 
|> IO.puts 
#=> Devastator 

(有在最后一个空字节,因此二进制显示,而不是字符串将在外壳中使用,这取决于操作系统时,可以打印一些额外的表示为空字节)

+0

啊,哇......我已经看过在Erlang库中,特别是'binary'来查看这些方法是否会对我有所帮助,但完全忽略了向下滚动页面并查看Unicode的内容......谢谢! – user701847

+1

这很好!我不知道':unicode.characters_ *'函数也接受二进制文件。 @ user701847你应该接受这个答案,而不是我的。 – Dogbert

1

您可以使用药剂的模式匹配,具体<<codepoint::utf16-little>>

defmodule Convert do 
    def utf16le_to_utf8(binary), do: utf16le_to_utf8(binary, "") 

    defp utf16le_to_utf8(<<codepoint::utf16-little, rest::binary>>, acc) do 
    utf16le_to_utf8(rest, <<acc::binary, codepoint::utf8>>) 
    end 
    defp utf16le_to_utf8("", acc), do: acc 
end 

<<68, 0, 101, 0, 118, 0, 97, 0, 115, 0, 116, 0, 97, 0, 116, 0, 111, 0, 114, 0, 0, 0>> 
|> Convert.utf16le_to_utf8 
|> IO.puts 

<<192, 3, 114, 0, 178, 0>> 
|> Convert.utf16le_to_utf8 
|> IO.puts 

输出:

Devastator 
πr² 
+1

啊,这就是我想念的,谢谢!我从未使用过'codepoint',然后像'codepoint :: utf8'那样匹配它;我基本上不知道如何处理2个字节。为了让你更简单,我们可以这样做:'for << codepoint :: utf16-little <- binary >>,into:“”,do:<< codepoint :: utf8>' – user701847