2016-09-29 51 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