需要Ruby方法将二进制数组转换为ASCII字母数字字符串

需要Ruby方法将二进制数组转换为ASCII字母数字字符串,ruby,Ruby,我有一个数组[1,0,11,0,4,0,106,211,169,1,0,12,0,8,0,1,1,26,25,32,189,77,216,1,0,1,0,4,0,0,0,12,15] 我想创建一个字符串版本,主要用于日志记录。我的最终结果将是“01000B0004006AD3…” 我找不到一种简单的方法来获取每个数组字节值并用ASCII表示的字节值打包字符串 我的解决方案很麻烦。我很感激关于如何使解决方案变得流畅的建议 array.each {|x| value = (x>>4

我有一个数组
[1,0,11,0,4,0,106,211,169,1,0,12,0,8,0,1,1,26,25,32,189,77,216,1,0,1,0,4,0,0,0,12,15]

我想创建一个字符串版本,主要用于日志记录。我的最终结果将是
“01000B0004006AD3…”

我找不到一种简单的方法来获取每个数组字节值并用ASCII表示的字节值打包字符串

我的解决方案很麻烦。我很感激关于如何使解决方案变得流畅的建议

array.each {|x| 
  value = (x>>4)&0x0f 
  if( value>9 ) then
    result_string.concat (value-0x0a + 'A'.ord).chr
  else
    result_string.concat (value + '0'.ord).chr
  end
  value = (x)&0x0f 
  if( value>9 ) then
    result_string.concat (value-0x0a + 'A'.ord).chr
  else
    result_string.concat (value + '0'.ord).chr
  end
}

你的问题不是很清楚,但我想这就是你想要的:

array.map {|n| n.to_s(16).rjust(2, '0').upcase }.join
#=> "01000B0004006AD3A901000C000800011A1920BD4DD80100010004000000000C0F"


我想,这两种格式中哪一种更具可读性取决于您的读者对
sprintf
样式的格式字符串的熟悉程度。

您的问题不是很清楚,但我想这正是您想要的:

array.map {|n| n.to_s(16).rjust(2, '0').upcase }.join
#=> "01000B0004006AD3A901000C000800011A1920BD4DD80100010004000000000C0F"


这两种格式中哪一种更具可读性取决于读者对
sprintf
样式的格式字符串的熟悉程度。

我可能建议您坚持使用十六进制或base64格式,而不是自己制作格式

dat = [1, 0, 11, 0, 4, 0, 106, 211, 169, 1, 0, 12, 0, 8, 0, 1, 26, 25, 32, 189, 77, 216, 1, 0, 1, 0, 4, 0, 0, 0, 0, 12, 15]
十六进制

hex = dat.map { |x| sprintf('%02x', x) }.join
# => 01000b0004006ad3a901000c000800011a1920bd4dd80100010004000000000c0f
Base64

require 'base64'
base64 = Base64.encode64(dat.pack('c*'))
# => AQALAAQAatOpAQAMAAgAARoZIL1N2AEAAQAEAAAAAAwP\n

proquits

什么?是可发音的唯一标识符,非常适合读取/传输二进制数据。在您的情况下,可能不是最好的,因为您在这里处理的是30多个字节,但它们非常适合较小的字节字符串

# proquint.rb
# adapted to ruby from https://github.com/deoxxa/proquint
module Proquint
  C = %w(b d f g h j k l m n p r s t v z)
  V = %w(a i o u)

  def self.encode (bytes)
    bytes << 0 if bytes.size & 1 == 1
    bytes.pack('c*').unpack('S*').reduce([]) do |acc, n|
      c1 = n         & 0x0f
      v1 = (n >> 4)  & 0x03
      c2 = (n >> 6)  & 0x0f
      v2 = (n >> 10) & 0x03
      c3 = (n >> 12) & 0x0f
      acc << C[c1] + V[v1] + C[c2] + V[v2] + C[c3]
    end.join('-')
  end

  def decode str
    # learner's exercise
    # or see some proquint library (eg) https://github.com/deoxxa/proquint
  end
end

Proquint.encode dat
# => dabab-rabab-habab-potat-nokab-babub-babob-bahab-pihod-bohur-tadot-dabab-dabab-habab-babab-babub-zabab

我可能建议您坚持使用十六进制或base64,而不是自己设置格式

dat = [1, 0, 11, 0, 4, 0, 106, 211, 169, 1, 0, 12, 0, 8, 0, 1, 26, 25, 32, 189, 77, 216, 1, 0, 1, 0, 4, 0, 0, 0, 0, 12, 15]
十六进制

hex = dat.map { |x| sprintf('%02x', x) }.join
# => 01000b0004006ad3a901000c000800011a1920bd4dd80100010004000000000c0f
Base64

require 'base64'
base64 = Base64.encode64(dat.pack('c*'))
# => AQALAAQAatOpAQAMAAgAARoZIL1N2AEAAQAEAAAAAAwP\n

proquits

什么?是可发音的唯一标识符,非常适合读取/传输二进制数据。在您的情况下,可能不是最好的,因为您在这里处理的是30多个字节,但它们非常适合较小的字节字符串

# proquint.rb
# adapted to ruby from https://github.com/deoxxa/proquint
module Proquint
  C = %w(b d f g h j k l m n p r s t v z)
  V = %w(a i o u)

  def self.encode (bytes)
    bytes << 0 if bytes.size & 1 == 1
    bytes.pack('c*').unpack('S*').reduce([]) do |acc, n|
      c1 = n         & 0x0f
      v1 = (n >> 4)  & 0x03
      c2 = (n >> 6)  & 0x0f
      v2 = (n >> 10) & 0x03
      c3 = (n >> 12) & 0x0f
      acc << C[c1] + V[v1] + C[c2] + V[v2] + C[c3]
    end.join('-')
  end

  def decode str
    # learner's exercise
    # or see some proquint library (eg) https://github.com/deoxxa/proquint
  end
end

Proquint.encode dat
# => dabab-rabab-habab-potat-nokab-babub-babob-bahab-pihod-bohur-tadot-dabab-dabab-habab-babab-babub-zabab

其实很简单:

def hexpack(data)
  data.pack('C*').unpack('H*')[0]
end
它使用整数值(
C
)打包字节,并将结果字符串解压为十六进制(
H
)。实际上:

hexpack([1, 0, 11, 0, 4, 0, 106, 211, 169, 1, 0, 12, 0, 8, 0, 1, 26, 25, 32, 189, 77, 216, 1, 0, 1, 0, 4, 0, 0, 0, 0, 12, 15])
# => "01000b0004006ad3a901000c000800011a1920bd4dd80100010004000000000c0f"

其实很简单:

def hexpack(data)
  data.pack('C*').unpack('H*')[0]
end
它使用整数值(
C
)打包字节,并将结果字符串解压为十六进制(
H
)。实际上:

hexpack([1, 0, 11, 0, 4, 0, 106, 211, 169, 1, 0, 12, 0, 8, 0, 1, 26, 25, 32, 189, 77, 216, 1, 0, 1, 0, 4, 0, 0, 0, 0, 12, 15])
# => "01000b0004006ad3a901000c000800011a1920bd4dd80100010004000000000c0f"

生病的ruby skills wrt
和“%02X”。方法(%)
谢谢@Jörg W Mittag生病的ruby skills wrt
和“%02X”。方法(%)
非常感谢@Jörg W Mittago。我完全忘记了斯普林特:正是我想要的!罗曼,我补充了另一个可能会让你吃惊的答案。如果有帮助,请告诉我。^我喜欢这个。我需要时间来消化。我重新开始使用ruby,我很喜欢:)这很酷:)我一直在使用mac-6字节值,几乎没有发音错误或误读的问题。我将尝试Proquint。Proquint适用于任何16位值。如果给定奇数,上述函数将自动填充字节。我完全忘记了斯普林特:正是我想要的!罗曼,我补充了另一个可能会让你吃惊的答案。如果有帮助,请告诉我。^我喜欢这个。我需要时间来消化。我重新开始使用ruby,我很喜欢:)这很酷:)我一直在使用mac-6字节值,几乎没有发音错误或误读的问题。我将尝试Proquint。Proquint适用于任何16位值。如果给定奇数,上述函数将自动填充字节