如何轻松转换数字,例如{10}在基数10中等效0x616263
,通过将数字除以连续字节而成为字符串?因此,上面的示例应转换为6382179
。
我已尝试Array.pack,但无法弄清楚如何让它转换为数字中的多个字节,例如'abc'
返回[0x616263].pack("C*")
。
我也试过了'c'
,但是抛出了一个ArgumentError:无效的基数。我想它需要某种编码信息?
(注意:像0x616263.to_s(256)
这样的包中的其他数据类型与我上面给出的示例一致,但仅仅因为它适合4个字节,所以例如N
给出[0x616263646566].pack("N")
,而不是cdef
abcdef
)
这个问题与this one模糊地相似,但不是真的。另外,我想弄清楚如何使用"abcde".unpack("c*").map{|c| c.to_s(16)}.join("")
从字符串中获取十六进制表示字符串,这会给出'6162636465'
。我基本上想要倒退。
我不认为这是X-Y problem,但如果是 - 我正在尝试将我用RSA解码的数字转换为字符串。
感谢您的帮助。我对Ruby没有太多经验。我也对Python解决方案感兴趣(为了好玩),但我不知道是否有权为这个问题添加两种不同编程语言的标签。
答案 0 :(得分:4)
要将单个数字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的答案。
答案 1 :(得分:3)
如果您的号码小于2 ** 64(8字节),您可以:
[0x616263].pack('Q>').sub(/\x00+/,'')
# "abc"
[0x616263646566].pack('Q>').sub(/\x00+/,'')
# "abcdef"
在Python中,pack
返回字节,而不是字符串。您可以decode()
使用convert bytes to a String:
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,则输出正确的字符串(例如,对于" \ t"):
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
解决方案的两倍。
答案 2 :(得分:2)
我目前正在努力:
n = 0x616263
nhex = n.to_s(16)
nhexarr = nhex.scan(/.{1,2}/)
nhexarr = nhexarr.map {|e| e.to_i(16)}
out = nhexarr.pack("C*")
但希望以简洁/内置的方式来做到这一点,所以我暂时不接受这个答案。