转自:http://wxianfeng.com/2012/05/27/ruby-array-pack-string-unpack
最近项目中常用到 Array#pack, String#unpack 方法,在此总结下:
Array#pack, String#unpack 可以实现不同编码之间的处理, 可以处理字节级, bit 级的一些二进制格式.
字节编码, ruby里主要是 “\nnn” 和 “\xnn” 的形式, nnn 是八进制数字, nn 是十六进制, 可以从 <<ruby编程语言>> 这本书看到相关信息.
截了张书中的图:
例子:
ASCII 码值: 0123456789
字节编码:
“\000\001\002\003\004\005\006\007\010\011” (八进制)
“\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09” (十六进制)
另外 ascii 码值是 7,8,9 的在ruby中是转义序列 “\a”, “\b”, “\t”, 所以字节编码也可以写成
\x00\x01\x02\x03\x04\x05\x06\a\b\t
1.9.2p290 :198 > a = [0,1,2,3,4,5,6,7,8,9] => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 1.9.2p290 :199 > a.pack("c*") => "\x00\x01\x02\x03\x04\x05\x06\a\b\t" 1.9.2p290 :200 > "\x00\x01\x02\x03\x04\x05\x06\a\b\t" == "\000\001\002\003\004\005\006\007\010\011" => true 1.9.2p290 :201 > "\011" == "\x09" => true 1.9.2p290 :202 > "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09" == "\000\001\002\003\004\005\006\007\010\011" => true
下面来看一些实例,以字符模板来讲
1, M
M | String | quoted printable, MIME encoding (see RFC2045)
字符串和 quoted printable 编码之间转换,常用在邮件编码中
Array#pack ruby-1.9.2-p290 :132 > ["[www.wxianfeng.com]欢迎您注册,请您激活"].pack("M") => "[www.wxianfeng.com]=E6=AC=A2=E8=BF=8E=E6=82=A8=E6=B3=A8=E5=86=8C,=E8=AF=B7=\n=E6=82=A8=E6=BF=80=E6=B4=BB=\n"
可以看到 每76个字符就多了一个 =\n , 所以如果是用在邮件的 Subject 的中的话, 应该是
["str"].pack("M").gsub(/=\n/,"")
完整的邮件Subject编码应该是 像这样:
value = ["[#{site}]请激活您的帐号"].pack("M").gsub(/=\n/, "") subject = "=?UTF-8?Q?#{value}?="
String#unpack ruby-1.9.2-p290 :153 > "[www.wxianfeng.com]=E6=AC=A2=E8=BF=8E=E6=82=A8=E6=B3=A8=E5=86=8C,=E8=AF=B7=\n=E6=82=A8=E6=BF=80=E6=B4=BB=\n".unpack("M") => ["[www.wxianfeng.com]\xE6\xAC\xA2\xE8\xBF\x8E\xE6\x82\xA8\xE6\xB3\xA8\xE5\x86\x8C,\xE8\xAF\xB7\xE6\x82\xA8\xE6\xBF\x80\xE6\xB4\xBB"]
2, m
m | String | base64 encoded string (see RFC 2045, count is width) | | (if count is 0, no line feed are added, see RFC 4648)
字符串和 Base64 编码之间转换
Array#pack ruby-1.9.2-p290 :133 > ["[www.wxianfeng.com]欢迎您注册,请您激活"].pack("m") => "W3d3dy53eGlhbmZlbmcuY29tXeasoui/juaCqOazqOWGjCzor7fmgqjmv4Dm\ntLs=\n"
base64编码也可以用在邮件编码中,例如用在Subject中就是这样:
value = ["[#{site}]请激活您的帐号"].pack("M").gsub(/=\n/, "") subject = "=?UTF-8?B?#{value}?="
String#unpack ruby-1.9.2-p290 :155 > "W3d3dy53eGlhbmZlbmcuY29tXeasoui/juaCqOazqOWGjCzor7fmgqjmv4Dm\ntLs=\n".unpack("m") => ["[www.wxianfeng.com]\xE6\xAC\xA2\xE8\xBF\x8E\xE6\x82\xA8\xE6\xB3\xA8\xE5\x86\x8C,\xE8\xAF\xB7\xE6\x82\xA8\xE6\xBF\x80\xE6\xB4\xBB"]
3, L
L | Integer | 32-bit unsigned, native endian (uint32_t)
整型(ASCII)和二进制字符串相互转化,int是32为无符号的,占4个字节
Array#pack ruby-1.9.2-p290 :139 > [65].pack("L") => "A\x00\x00\x00" String#unpack ruby-1.9.2-p290 :140 > "A\x00\x00\x00".unpack("L") => [65]
4, c
c | Integer | 8-bit signed (signed char)
整型(ASCII)和二进制字符串相互转化,int 是8位有符号的,占一个字节
Array#pack ruby-1.9.2-p290 :142 > [77].pack("c") => "M" String#unpack ruby-1.9.2-p290 :143 > "M".unpack("c") => [77]
5, Q
Q | Integer | 64-bit unsigned, native endian (uint64_t)
整型和二进制字符串相互转化,int是64位无符号的,占8字节
Array#pack ruby-1.9.2-p290 :149 > [1338053358065].pack("Q") => "\xF1\xF11\x8A7\x01\x00\x00" String#unpack ruby-1.9.2-p290 :150 > "\xF1\xF11\x8A7\x01\x00\x00".unpack("Q") => [1338053358065]
6, S
S | Integer | 16-bit unsigned, native endian (uint16_t)
整型和二进制字符串转化,int是16位无符号的,占2个字节
Array#pack ruby-1.9.2-p290 :151 > [6].pack("S") => "\x06\x00" String#unpack ruby-1.9.2-p290 :152 > "\x06\x00".unpack("S") => [6]