python 对于整数有个处理方法 to_bytes,转换后可以进行网络的 socket 传输 int.to_bytes(length, byteorder, *, signed=False) Return an array of bytes representing an integer.
请问 ruby 有对应的方法吗? 在网上查了一下,array 有 pack 方法,但是试了所有的方法都达不到 python 的 to_bytes 方法的效果
哈,当年写的代码终于有用了:
https://github.com/windy/DIY-pcap/blob/master/lib/diy/parser/mu/pcap/ethernet.rb#L93
这是一段解析以太网 2 层报文的代码,估计比你的需求满足:
ADDR_TO_BYTES = {}
FMT_HEADER = 'a6a6n'
def write io
dst_mac = ADDR_TO_BYTES[@dst] ||= @dst.split(':').inject('') {|m, b| m << b.to_i(16).chr}
src_mac = ADDR_TO_BYTES[@src] ||= @src.split(':').inject('') {|m, b| m << b.to_i(16).chr}
bytes = [dst_mac, src_mac, @type].pack(FMT_HEADER)
io.write bytes
if @payload.is_a? String
io.write @payload
else
@payload.write io
end
end
@haoshanshan 例子都给你了,自己不会看吗?这段代码把数据转为二进制网络序,下一步就是发送。
具体的看 pack : http://ruby-doc.org/core-2.2.0/Array.html#method-i-pack
固定长度的整数 (1, 2, 4, 8 字节) 用 pack
可以。
适合网络传输的任意长整数,用 der 格式最适合了,我推荐这个:
[70244200243420].pack 'w' #=> "\x8F\xFC\xB0\x84\xE9\xC1\\"
"\x8F\xFC\xB0\x84\xE9\xC1\\".unpack 'w' #=> [70244200243420]
如果是要生翻译 python 的 to_bytes
, 就没内建的方法,得自己写了,只支持 unsigned 的例子如下:
class Integer
def to_bytes size, byteorder: 'big'
i = self
rs = size.times.map do
i, r = i.divmod 256
r
end
rs.reverse! if byteorder == 'big'
rs.pack 'C*'
end
end
基本上搞定了。多谢 luikore irb(main):009:0> ["\x02"].pack("a2").reverse => "\x00\x02" 查看了一下需要实现的需求,就是只需要转换二进制后用 1,2 或 4 字节表示
之前一直纠结 12 转换后成/f,与/x0c 不一致,结果/f 与/x0c 是相等的。多谢 china ruby 的大牛们,终于搞定
使用 ["\x02"].pack("a2").reverse 处理 10004000,处理的不对,最后还是使用了@luikore的方法,在 integer 中加了这个方法,在 irb 中可以直接 12.to_bytes 1 方法,但是在文件中老是提示 fixnum 没有定义,找 fixnum 的定义文件,加了后还是不行,就直接改了一下
def to_bytes num,size
rs = size.times.map do
num, r = num.divmod 256
r
end
rs.reverse.pack 'C*'
end
问题最终得到解决,真是十二分感谢@luikore
如果来成都,找我(qq:30711905)
#9 楼 @haoshanshan 呃,改现有 class 例如 Fixnum, Integer 不用找那个文件的,直接在你的代码中写就行 (虽然大一点工程不推荐,但小脚本随便用没关系).
另外你早点说 big endian, 只用搞 1, 2, 4 字节就好了嘛,很简单:
[num].pack 'C' # 1 字节
[num].pack 'S>' # 2 字节
[num].pack 'L>' # 4 字节
这些参数怎么来的?命令行 ri pack
可以看到