如何轻松转换数字,例如
0x616263
,相当于以 10 为基数的 6382179
,通过将数字分成连续的字节来转换为字符串?所以上面的例子应该转换成'abc'
。
我已经尝试过 Array.pack 但无法弄清楚如何让它转换数字中的多个字节,例如
[0x616263].pack("C*")
返回 'c'
。
我也尝试过 0x616263.to_s(256)
,但这会引发 ArgumentError: invalid radix。我想它需要某种编码信息?
(注意:包中的其他数据类型(如
N
)适用于我上面给出的示例,但只是因为它适合 4 个字节,因此例如 [0x616263646566].pack("N")
给出 cdef
,而不是 abcdef
)
这个问题与这个问题隐约相似,但并非如此。另外,我还想出了如何使用
"abcde".unpack("c*").map{|c| c.to_s(16)}.join("")
从字符串中获取十六进制表示字符串,这给出了 '6162636465'
。我基本上想倒退。
我不认为这是一个 X-Y 问题,但万一它是 - 我正在尝试将用 RSA 解码的数字转换为字符串。
感谢您的帮助。我对 Ruby 不太有经验。我也对 Python 解决方案感兴趣(为了好玩),但我不知道为这个问题添加两种单独的编程语言的标签是否正确。
要将单个数字
0x00616263
转换为3个字符,您首先需要做的是将它们分成三个数字:0x00000061
、0x00000062
和0x00000063
。
对于最后一个数字,您想要的十六进制数字已经位于正确的位置。但对于另外两个,您必须分别使用
>> 16
和 >> 8
进行位移。
然后,使用按位与 (
&
) 去掉其他数字:
num1 = (0x616263 >> 16) & 0xFF
num2 = (0x616263 >> 8) & 0xFF
num3 = 0x616263 & 0xFF
对于角色,你可以这样做:
char1 = ((0x616263 >> 16) & 0xFF).chr
char2 = ((0x616263 >> 8) & 0xFF).chr
char3 = (0x616263 & 0xFF).chr
当然,按位运算并不是很 Ruby 风格。其他人可能会提供更多类似 Ruby 的答案。
如果您的号码小于2**64(8字节),您可以:
[0x616263].pack('Q>').sub(/\x00+/,'')
# "abc"
[0x616263646566].pack('Q>').sub(/\x00+/,'')
# "abcdef"
pack
返回字节,而不是字符串。您可以使用 decode()
将字节转换为字符串 :
import struct
import re
print(re.sub('\x00', '', struct.pack(">Q", 0x616263646566).decode()))
# abcdef
print(re.sub('\x00', '', struct.pack(">Q", 0x616263).decode()))
# abc
如果您的号码无法容纳 8 个字节,您可以使用代码的修改版本。如果第一个字节小于 10(例如“”),这会更短并正确输出字符串:
def decode(int)
if int < 2**64
[int].pack('Q>').sub(/\x00+/, '')
else
nhex = int.to_s(16)
nhex = '0' + nhex if nhex.size.odd?
nhex.gsub(/../) { |hh| hh.to_i(16).chr }
end
end
puts decode(0x616263) == 'abc'
# true
puts decode(0x616263646566) == 'abcdef'
# true
puts decode(0x0961) == "\ta"
# true
puts decode(0x546869732073656e74656e63652069732077617920746f6f206c6f6e6720666f7220616e20496e743634)
# This sentence is way too long for an Int64
顺便说一句,这是相反的方法:
def encode(str)
str.reverse.each_byte.with_index.map { |b, i| b * 256**i }.inject(:+)
end
您仍然应该检查您的 RSA 代码是否确实输出任意大数或只是整数数组。
这是获得结果的另一种方法。它与 @Nathan 的答案类似,但它适用于任何整数大小:
def decode(int)
a = []
while int>0
a << (int & 0xFF)
int >>= 8
end
a.reverse.pack('C*')
end
fruity
,它的速度是gsub
解决方案的两倍。
我目前正在研究这个:
n = 0x616263
nhex = n.to_s(16)
nhexarr = nhex.scan(/.{1,2}/)
nhexarr = nhexarr.map {|e| e.to_i(16)}
out = nhexarr.pack("C*")
但是希望有一种简洁/内置的方法来做到这一点,所以我暂时不接受这个答案。