【问题标题】:Converting a UTF-16LE Elixir bitstring into an Elixir String将 UTF-16LE Elixir 位串转换为 Elixir 字符串
【发布时间】:2017-02-07 23:04:01
【问题描述】:

给定一个以 UTF-16LE 编码的 Elixir 位串:

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

我怎样才能把它转换成可读的 Elixir 字符串(它拼写为“Devastator”)?我得到的最接近的是将上面的内容转换为 Unicode 代码点列表 (["0044", "0065", ...]) 并尝试在它们前面加上 \u 转义序列,但 Elixir 抛出错误,因为它是无效序列。我没有想法。

【问题讨论】:

  • 你已经answered这个问题了,不是吗?
  • 这是一个临时的 hack,适用于更复杂的情况,例如解析以空字节结尾的未知长度的字符串,这是不够的。

标签: utf-8 elixir utf-16 utf-16le


【解决方案1】:

你可以使用 Elixir 的模式匹配,特别是 &lt;&lt;codepoint::utf16-little&gt;&gt;:

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²

【讨论】:

  • 啊,这就是我所缺少的,谢谢!我从来没有拿过codepoint,然后像codepoint::utf8一样匹配它;我基本上不知道如何处理这 2 个字节。为了让您更简单,我们可以这样做:for &lt;&lt; codepoint::utf16-little &lt;- binary &gt;&gt;, into: "", do: &lt;&lt;codepoint::utf8&gt;
【解决方案2】:

最简单的方法是使用 :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

(最后有一个空字节,因此shell中将使用二进制显示而不是字符串,并且根据操作系统,它可能会为空字节打印一些额外的表示)

【讨论】:

  • 啊,哇...我实际上已经在 Erlang 库中四处看了看,特别是 binary 看看这些方法是否对我有帮助,但完全忽略了向下滚动页面并查看Unicode 一...谢谢!
  • 这很好!我不知道:unicode.characters_* 函数也接受二进制文件。 @user701847 你可能应该接受这个答案而不是我的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 1970-01-01
  • 2019-11-18
  • 2020-06-29
  • 2017-03-19
  • 1970-01-01
相关资源
最近更新 更多