Ruby string#unpack

在学习字符串压缩之前,需要了解一些基础知识。

1. 比特(bit)运算

(1)比特(bit),台湾称为“位”,是计算机中最小的数据单位,每一个bit的值是0或者1。
(2)字节(Byte):8个二进制位构成一个字节,字节是存储空间的基本计量单位。1个字节可以存储一个英文字母或者半个汉字,也就是说一个汉字需要两个字节存储。
(3)换算

1
2
3
4
5
6
7
8
# 二进制换算
1Byte = 8bits
1Byte = 2nibbles
1nibble = 4bits

#十进制换算
1Byte(B)= 8bits(b)
1KB = 1000bytes

(4)基本术语

  • most significant bit ————- 最高有效位
  • least significant bit ————- 最低有效位
  • ASCII ———————————– 美国信息交换标准代码:在计算机中,所有的数据在存储和运算时都以二进制表示,比如汉字、字符、英文等。
  • hex :十六进制; dec: 十进制; oct:八进制; bin:二进制
  • unpack: 解压; pack:压缩。

2. String unpack

String unpack and Array pack.

1
2
3
4
5
> 'jonathan'.unpack('C*').map{|i| i.to_s 2}
=> ["1101010", "1101111", "1101110", "1100001", "1110100", "1101000", "1100001", "1101110"]

> 'jonathan'.unpack('B*')
=> ["0110101001101111011011100110000101110100011010000110000101101110"]

上面这个例子的意思是将'jonathan' 这个字符串的每个字符解压成二进制位。

1
2
> 'jonathan'.unpack('C*')
=> [106, 111, 110, 97, 116, 104, 97, 110]

上面例子是将'jonathan'这个字符串解压为十进制位。

1
2
3
4
5
> 'jonathan'.unpack('H*')
=> ["6a6f6e617468616e"]

> 'jonathan'.unpack('C*').map{|i| i.to_s 16}
=> ["6a", "6f", "6e", "61", "74", "68", "61", "6e"]

上面这个例子是将'jonathan' 这个字符串解压成16进制位。
更过例子:

1
2
3
4
5
6
7
8
"abc \0\0abc \0\0".unpack('A6Z6')  #=> ["abc", "abc "]
"abc \0\0".unpack('a3a3') #=> ["abc", " \000\000"]
"abc \0abc \0".unpack('Z*Z*') #=> ["abc ", "abc "]
"aa".unpack('b8B8') #=> ["10000110", "01100001"]
"aaa".unpack('h2H2c') #=> ["16", "61", 97]
"\xfe\xff\xfe\xff".unpack('sS') #=> [-2, 65534]
"now=20is".unpack('M*') #=> ["now is"]
"whole".unpack('xax2aX2aX1aX2a') #=> ["h", "e", "l", "l", "o"]

3. 参考资料

ASCII百度百科
Ruby pack unpack
Ruby中操作字符串的基本方法
Packing & Unpacking: A Guide to Reading Binary Data in Ruby