输入: [ 65, 66, 67 ] 输出: "ABC"
这个代码我怎么也写不好,求助各位 ( 输出内容可能包含不可见字符串,这个没关系,我是拿来做 rsa 加解密的 )
刚好 Array#pack 的例子就适合你: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-pack
n = [ 65, 66, 67 ]
n.pack("ccc") #=> "ABC"
[1] pry(main)> "ABC".unpack("C*")
=> [65, 66, 67]
[2] pry(main)> "ABC".unpack("C*").pack("U*")
=> "ABC"
>> 1234.chr
RangeError: 1234 out of char range
from (irb):14:in `chr'
from (irb):14
ascii 可以用 chr,其他的码点就不行了。
s.pack('C*')
就可以,不用特意给长度,c
对应 -128 到 127,C
对应 0 到 255,C
才和 chr 对应(只要不是 C# 弄出来的有符号字节数组一般都没必要用 c
⋯⋯)
@fsword pack 的格式字符串的确是和 perl 一样的。转换 little endian / big endian,转换 C 数据类型的时候没有 pack / unpack 就得写一大堆还容易出错⋯⋯
例如用 unpack 读 wav 格式的文件超简单:
data = ARGF.read
keys = %w[id totallength wavefmt format
pcm channels frequency bytes_per_second
bytes_by_capture bits_per_sample
data bytes_in_data sum
]
values = data.unpack 'Z4 i Z8 i s s i i s s Z4 i s*'
sum = values.drop(12).map(&:abs).inject(:+)
keys.zip(values.take(12) << sum) {|k, v|
puts "#{k.ljust 17}: #{v}"
}
补充说明一下⋯⋯ wave 文件有这些字段
Z4 id
i totallength
Z8 wavefmt
i format
s pcm
s channels
i frequency
i bytes_per_second
s bytes_by_capture
s bits_per_sample
Z4 data
i bytes_in_data
s* 数据
顾名思义 i
是整数
Z
是 ascii 字符,但额外的 '\0' 也算合法字符
s
是 short, 有符号 16 位整数
最后算 sum 的请忽略⋯⋯ 当时是吐槽这个人 http://yannesposito.com/Scratch/en/blog/2010-10-14-Fun-with-wav/ 写的⋯⋯
看明白了...
原来 unpack 在这种情况下,真的很强大啊!原来看 pack, unpack 一大堆数据类型,不知道到底要干什么,现在明白了。
虽然说忽略... 不过后面的代码也是用活,用好 Ruby API 的典范啊!!
太赞了!!