Ruby 关于整型数组到字符串的转换

fsword · 2012年05月21日 · 最后由 cisolarix 回复于 2014年01月04日 · 8006 次阅读

输入: [ 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"

你们好快啊。。。

#3 楼 @hooopo 哈哈哈,此类贴肯定是秒杀,大家都在埋伏着呢。

#4 楼 @skandhas

我靠~ 还记不记得前几天我刚刚因为这个问题,问过你啊~

用 pack 也太晦涩了,用这个。

s.map {|ch| ch.chr }.join

#5 楼 @zw963

>> 1234.chr
RangeError: 1234 out of char range
    from (irb):14:in `chr'
    from (irb):14

ascii 可以用 chr,其他的码点就不行了。

#6 楼 @hooopo

哦。我倒是没考虑这个。如果那样的话,只能用 pack 了。

不过即使用 pack, 也应该判断数组元素的数量。

p s.pack("c" * s.length)

pack 我始终觉得太晦涩,有种 perl 的感觉

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}"
}

#10 楼 @night_song

+1. 太赞了!!!

不过,愣是没看懂这代码是干嘛...

补充说明一下⋯⋯ 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/ 写的⋯⋯

#10 楼 @night_song

看明白了...

原来 unpack 在这种情况下,真的很强大啊!原来看 pack, unpack 一大堆数据类型,不知道到底要干什么,现在明白了。

#13 楼 @night_song

虽然说忽略... 不过后面的代码也是用活,用好 Ruby API 的典范啊!!

太赞了!!

同意 #14 楼@night_song API 掌握的相当好啊。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号