hex - 如何使用 Elixir 打包/解包十六进制字符串(先是高半字节)

标签 hex elixir

我想知道如何在 Elixir 中使用十六进制字符串。具体来说,我对从十六进制转换为 ASCII 感兴趣。

在 Ruby 中,其实现可能是:

["001C7F616A8B002128C1A33E8100"].pack('H*').gsub(/[^[:print:]]/, '.')

我如何使用 Elixir 完成这项任务?我尝试过:

<<00, 01, C7, F6...>>

但这不是字符串的十六进制的正确表示。感谢您的时间和帮助!

所以我已经取得了一些进展,但目前正在努力解决递归方面的问题。

这是我迄今为止的解决方案:

defmodule ElixirNetworkTools do
  def decode(payload) do
    upper_payload = String.upcase payload
    case Base.decode16(upper_payload) do
      :error -> decode_with_nonprintable_characters(payload)
      {:ok, decoded_payload} -> decoded_payload
    end
    |> IO.write
  end

def decode_with_nonprintable_characters(payload) do
String.chunk(payload, ~r/\w{2}/)
|> Enum.each(fn(byte) ->
  case Base.decode16(byte) do
    :error -> '.'
    {:ok, decoded_payload} -> decoded_payload
      end
    end)
  end
end

最佳答案

这是该问题的另一种解决方案。在我们开始之前有几件事:

  • 您可以将 case: :mixed 传递给 Base.decode16/2:Base.decode16(string, case: :mixed) code>,因此,之前不需要进行大写操作。

  • 如果您要引发无效字符串,请不必费心检查,只需直接调用decode16,因为它也会检查大小。

这意味着我们可以从以下开始:

decoded = Base.decode16!(string, case: :mixed)

现在您需要替换不可打印的字符。不要使用 String.printable?/1 因为它是关于 UTF-8 而不是 ASCII。我们需要实现我们自己的功能,但什么更有意义:提高或替换它们?看来如果有人发送无效数据就必须被视为错误?如果是这样的话:

def validate_ascii!(<<h, t::binary>>) when h <= 127 do
  validate_ascii!(t)
end

def validate_ascii!(<<>>) do
  true
end

def validate_ascii!(rest) do
  raise "invalid ascii on string starting at: #{rest}"
end

或者,您可以只删除最后一个子句,它也会失败。

现在我们可以将它们放在一起:

decoded = Base.decode16!(string, case: :mixed)
validate_ascii!(decoded)
decoded

编辑:如果您需要用点替换非 ASCII:

def keep_ascii(<<h, t::binary>>, acc) when h <= 127 do
  keep_ascii(t, acc <> <<h>>)
end

def keep_ascii(<<_, t::binary>>, acc) do
  keep_ascii(t, acc <> ".")
end

def keep_ascii(<<>>, acc) do
  acc
end

关于hex - 如何使用 Elixir 打包/解包十六进制字符串(先是高半字节),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30104153/

相关文章:

css - 浏览器如何处理 rgb(percentage);对于奇怪的数字

string - 在lua中将字符串转换为十六进制?

将由 0's and 1' 组成的十六进制转换为等效的二进制

pattern-matching - 如何在 Elixir 的功能头中对映射键进行模式匹配

authentication - 在没有模型的情况下使用 Guardian

c - 如何将十进制整数转换为单个十六进制字符? (C)

c++ - 为什么 DWORD 值通常以十六进制表示?

elixir - Phoenix channel 的广播如何影响其他节点上的客户端?

list - 比较两个列表是否相等的惯用方式是什么?

elixir - 如何修改 Changeset 中的值 - Elixir?