目录搜索
Ruby用户指南3、开始4、简单的例子5、字符串6、正则表达式7、数组8、回到那些简单的例子9、流程控制10、迭代器11、面向对象思维12、方法13、类14、继承15、重载方法16、访问控制17、单态方法18、模块19、过程对象20、变量21、全局变量22、实变量23、局部变量24、类常量25、异常处理:rescue26、异常处理:ensure27、存取器28、对象的初始化29、杂项RGSS入门教程1、什么是RGSS2、开始:最简单的脚本3、数据类型:数字4、数据类型:常量与变量5、数据类型:字符串6、控制语句:条件分歧语句7、控制语句:循环8、函数9、对象与类10、显示图片11、数组12、哈希表(关联数组)13、类14、数据库15、游戏对象16、精灵的管理17、窗口的管理18、活动指令19、场景类Programming Ruby的翻译Programming Ruby: The Pragmatic Programmer's Guide前言RoadmapRuby.new类,对象和变量容器Containers,块Blocks和迭代Iterators标准类型深入方法表达式Expressions异常,捕捉和抛出(已经开始,by jellen)模块基本输入输出线程和进程当遭遇挫折Ruby和它的世界Ruby和Web开发Ruby TkRuby 和微软的 Windows扩展RubyRuby语言 (by jellen)类和对象 (by jellen)Ruby安全反射Reflection内建类和方法标准库OO设计网络和Web库Windows支持内嵌文档交互式Ruby Shell支持Ruby参考手册Ruby首页卷首语Ruby的启动环境变量对象执行结束时的相关处理线程安全模型正则表达式字句构造程序变量和常数字面值操作符表达式控制结构方法调用类/方法的定义内部函数内部变量内部常数内部类/模块/异常类附加库Ruby变更记录ruby 1.6 特性ruby 1.7 特性Ruby术语集Ruby的运行平台pack模板字符串sprintf格式Marshal格式Ruby FAQRuby的陷阱
文字

pack模板字符串

下面就是Array#pack、String#unpack中所用到的模板字符的一览表。模板字符后面可以跟上表示"长度"的数字。若使用'*'来取代"长度"的话, 则表示"剩下的所有字符"之意。

长度的定义因模板字符的不同而有所差异, 大体上像

"iiii"

这样的连续字符可以写成

"i4"

这个样子。

在下面的说明中, short和long分别表示长度为2和4字节的数值(也就是通常32位机器所指的short和long的大小), 这与具体的系统无关。 若`s', `S', `l', `L'后面出现`_'或`!'(如"s!")的话, 则表示这个short或long的大小取决于具体的系统。

请注意: `i', `I' (int)的大小总是取决于系统的, 而`n', `N', `v', `V'的大小则是系统无关的(不能添加`!')。

模板字符串中的空格会被忽略。 ruby 1.7 特性: 另外,从`#'开始到换行处或者到模板字符串结尾之间的部分会被看做是注释。

在下面的说明中, 若针对某问题Array#pack和String#unpack有不同的解释时, 就使用/将两者分开, 即采用 "Array#pack的说明部分/String#unpack的说明部分" 的形式加以说明.

  • a

    ASCII字符串(塞入null字符/保留后续的null字符或空格)

    ["abc"].pack("a") => "a"
    ["abc"].pack("a*") => "abc"
    ["abc"].pack("a4") => "abc\0"
    
    "abc\0".unpack("a4") => ["abc\0"]
    "abc ".unpack("a4") => ["abc "]
    
  • A

    ASCII字符串(塞入空格/删除后续的null字符和空格)

    ["abc"].pack("A") => "a"
    ["abc"].pack("A*") => "abc"
    ["abc"].pack("A4") => "abc "
    
    "abc ".unpack("A4") => ["abc"]
    "abc\0".unpack("A4") => ["abc"]
    
  • Z

    null终点字符串(与a相同 / 删除后续的null字符)

    ["abc"].pack("Z") => "a"
    ["abc"].pack("Z*") => "abc"
    ["abc"].pack("Z4") => "abc\0"
    
    "abc\0".unpack("Z4") => ["abc"]
    "abc ".unpack("Z4") => ["abc "]
    
  • b

    位串(从下级位到上级位)

    "\001\002".unpack("b*") => ["1000000001000000"]
    "\001\002".unpack("b3") => ["100"]
    
    
    ["1000000001000000"].pack("b*") => "\001\002"
    
  • B

    位串(从上级位到下级位)

    "\001\002".unpack("B*") => ["0000000100000010"]
    "\001\002".unpack("B9") => ["000000010"]
    
    ["0000000100000010"].pack("B*") => "\001\002"
    
  • h

    16进制字符串(下级半字节(nibble)在先)

    "\x01\xfe".unpack("h*") => ["10ef"]
    "\x01\xfe".unpack("h3") => ["10e"]
    
    ["10ef"].pack("h*") => "\001\376"
    
  • H

    16进制字符串(上级半字节在先)

    "\x01\xfe".unpack("H*") => ["01fe"]
    "\x01\xfe".unpack("H3") => ["01f"]
    
    ["01fe"].pack("H*") => "\001\376"
    
  • c

    char (8bit 有符号整数)

    "\001\376".unpack("c*") => [1, -2]
    
    [1, -2].pack("c*") => "\001\376"
    [1, 254].pack("c*") => "\001\376"
    
  • C

    unsigned char (8bit 无符号整数)

    "\001\376".unpack("C*") => [1, 254]
    
    [1, -2].pack("C*") => "\001\376"
    [1, 254].pack("C*") => "\001\376"
    
  • s

    short (16bit 有符号整数, 取决于Endian) (s! 并非16bit, 它取决于short的大小)

    小Endian:

    "\001\002\376\375".unpack("s*") => [513, -514]
    
    [513, 65022].pack("s*") => "\001\002\376\375"
    [513, -514].pack("s*") => "\001\002\376\375"
    

    大Endian:

    "\001\002\376\375".unpack("s*") => [258, -259]
    
    [258, 65277].pack("s*") => "\001\002\376\375"
    [258, -259].pack("s*") => "\001\002\376\375"
    
  • S

    unsigned short (16bit 无符号整数, 取决于Endian) (S!并非16bit,它取决于short 的大小)

    小Endian:

    "\001\002\376\375".unpack("S*") => [513, 65022]
    
    [513, 65022].pack("s*") => "\001\002\376\375"
    [513, -514].pack("s*") => "\001\002\376\375"
    

    大Endian:

    "\001\002\376\375".unpack("S*") => [258, 65277]
    
    [258, 65277].pack("S*") => "\001\002\376\375"
    [258, -259].pack("S*") => "\001\002\376\375"
    
  • i

    int (有符号整数, 取决于Endian和int的大小)

    小Endian, 32bit int:

    "\001\002\003\004\377\376\375\374".unpack("i*") => [67305985, -50462977]
    
    [67305985, 4244504319].pack("i*") => RangeError
    [67305985, -50462977].pack("i*") => "\001\002\003\004\377\376\375\374"
    

    大Endian, 32bit int:

    "\001\002\003\004\377\376\375\374".unpack("i*") => [16909060, -66052]
    
    [16909060, 4294901244].pack("i*") => RangeError
    [16909060, -66052].pack("i*") => "\001\002\003\004\377\376\375\374"
    
  • I

    unsigned int (无符号整数, 取决于Endian和int的大小)

    小Endian, 32bit int:

    "\001\002\003\004\377\376\375\374".unpack("I*") => [67305985, 4244504319]
    
    [67305985, 4244504319].pack("I*") => "\001\002\003\004\377\376\375\374"
    [67305985, -50462977].pack("I*") => "\001\002\003\004\377\376\375\374"
    

    大Endian, 32bit int:

    "\001\002\003\004\377\376\375\374".unpack("I*") => [16909060, 4294901244]
    
    [16909060, 4294901244].pack("I*") => "\001\002\003\004\377\376\375\374"
    [16909060, -66052].pack("I*") => "\001\002\003\004\377\376\375\374"
    
  • l

    long (32bit 有符号整数, 取决于Endian) (l! 并非32bit, 它取决于long的大小)

    小Endian, 32bit long:

    "\001\002\003\004\377\376\375\374".unpack("l*") => [67305985, -50462977]
    
    [67305985, 4244504319].pack("l*") => RangeError
    [67305985, -50462977].pack("l*") => "\001\002\003\004\377\376\375\374"
    
  • L

    unsigned long (32bit 无符号整数, 取决于Endian) (L! 并非32bit, 它取决于long的大小)

    小Endian, 32bit long:

    "\001\002\003\004\377\376\375\374".unpack("L*") => [67305985, 4244504319]
    
    [67305985, 4244504319].pack("L*") => "\001\002\003\004\377\376\375\374"
    [67305985, -50462977].pack("L*") => "\001\002\003\004\377\376\375\374"
    
  • q

    ruby 1.7 特性: long long (有符号整数, 取决于Endian和long long 的大小) (在C中无法处理long long时, 就是64bit)

    小Endian, 64bit long long:

    "\001\002\003\004\005\006\007\010\377\376\375\374\373\372\371\370".unpack("q*")
    => [578437695752307201, -506097522914230529]
    
    [578437695752307201, -506097522914230529].pack("q*")
    => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370"
    [578437695752307201, 17940646550795321087].pack("q*")
    => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370"
    
  • Q

    ruby 1.7 特性: unsigned long long (无符号整数, 取决于Endian和 long long 的大小) (在C中无法处理long long时, 就是64bit)

    小Endian, 64bit long long:

    "\001\002\003\004\005\006\007\010\377\376\375\374\373\372\371\370".unpack("Q*")
    => [578437695752307201, 17940646550795321087]
    
    [578437695752307201, 17940646550795321087].pack("Q*")
    => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370"
    [578437695752307201, -506097522914230529].pack("Q*")
    => "\001\002\003\004\005\006\a\010\377\376\375\374\373\372\371\370"
    
  • m

    被base64编码过的字符串。每隔60个八位组(或在结尾)添加一个换行代码。

    Base64是一种编码方法, 它只使用ASCII码中的65个字符(包括[A-Za-z0-9+/]这64字符和用来padding的'='),将3个八位组(8bits * 3 = 24bits)中的二进制代码转为4个(6bits * 4 = 24bits)可印刷的字符。具体细节请参考RFC2045。

    [""].pack("m") => ""
    ["\0"].pack("m") => "AA==\n"
    ["\0\0"].pack("m") => "AAA=\n"
    ["\0\0\0"].pack("m") => "AAAA\n"
    ["\377"].pack("m") => "/w==\n"
    ["\377\377"].pack("m") => "//8=\n"
    ["\377\377\377"].pack("m") => "////\n"
    
    ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"].pack("m")
    => "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n"
    ["abcdefghijklmnopqrstuvwxyz"].pack("m3")
    => "YWJj\nZGVm\nZ2hp\namts\nbW5v\ncHFy\nc3R1\ndnd4\neXo=\n"
    
    "".unpack("m") => [""]
    "AA==\n".unpack("m") => ["\000"]
    "AA==".unpack("m") => ["\000"]
    
    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJT\nVFVWV1hZWg==\n".unpack("m")
    => ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]
    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWg==\n".unpack("m")
    => ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]
    
  • M

    经过quoted-printable encoding编码的字符串

    ["a b c\td \ne"].pack("M") => "a b c\td =\n\ne=\n"
    
    "a b c\td =\n\ne=\n".unpack("M") => ["a b c\td \ne"]
    
  • n

    网络字节顺序(大Endian)的unsigned short (16bit 无符号整数)

    [0,1,-1,32767,-32768,65535].pack("n*")
    => "\000\000\000\001\377\377\177\377\200\000\377\377"
    
    "\000\000\000\001\377\377\177\377\200\000\377\377".unpack("n*")
    => [0, 1, 65535, 32767, 32768, 65535]
    
  • N

    网络字节顺序(大Endian)的unsigned long (32bit 无符号整数)

    [0,1,-1].pack("N*") => "\000\000\000\000\000\000\000\001\377\377\377\377"
    
    "\000\000\000\000\000\000\000\001\377\377\377\377".unpack("N*") => [0, 1, 4294967295]
    
  • v

    "VAX"字节顺序(小Endian)的unsigned short (16bit 无符号整数)

    [0,1,-1,32767,-32768,65535].pack("v*")
    => "\000\000\001\000\377\377\377\177\000\200\377\377"
    
    "\000\000\001\000\377\377\377\177\000\200\377\377".unpack("v*")
    => [0, 1, 65535, 32767, 32768, 65535]
    
  • V

    "VAX"字节顺序(小Endian)的unsigned long (32bit 无符号整数)

    [0,1,-1].pack("V*") => "\000\000\000\000\001\000\000\000\377\377\377\377"
    
    "\000\000\000\000\001\000\000\000\377\377\377\377".unpack("V*") => [0, 1, 4294967295]
    
  • f

    单精度浮点数(取决于系统)

    IA-32 (x86) (IEEE754 单精度 小Endian):

    [1.0].pack("f") => "\000\000\200?"
    

    sparc (IEEE754 单精度 大Endian):

    [1.0].pack("f") => "?\200\000\000"
    
  • d

    双精度浮点数(取决于系统)

    IA-32 (IEEE754 双精度 小Endian):

    [1.0].pack("d") => "\000\000\000\000\000\000\360?"
    

    sparc (IEEE754 双精度 大Endian):

    [1.0].pack("d") => "?\360\000\000\000\000\000\000"
    
  • e

    小Endian的单精度浮点数(取决于系统)

    IA-32:

    [1.0].pack("e") => "\000\000\200?"
    

    sparc:

    [1.0].pack("e") => "\000\000\200?"
    
  • E

    小Endian的双精度浮点数(取决于系统)

    IA-32:

    [1.0].pack("E") => "\000\000\000\000\000\000\360?"
    

    sparc:

    [1.0].pack("E") => "\000\000\000\000\000\000\360?"
    
  • g

    大Endian的单精度浮点数(取决于系统)

    IA-32:

    [1.0].pack("g") => "?\200\000\000"
    

    sparc:

    [1.0].pack("g") => "?\200\000\000"
    
  • G

    大Endian的双精度浮点数(取决于系统)

    IA-32:

    [1.0].pack("G") => "?\360\000\000\000\000\000\000"
    

    sparc:

    [1.0].pack("G") => "?\360\000\000\000\000\000\000"
    
  • p

    指向null终点字符串的指针

    [""].pack("p") => "\310\037\034\010"
    ["a", "b", "c"].pack("p3") => " =\030\010\340^\030\010\360^\030\010"
    [nil].pack("p") => "\000\000\000\000"
    
  • P

    指向结构体(定长字符串)的指针

    [nil].pack("P") => "\000\000\000\000"
    ["abc"].pack("P3") => "x*\024\010"
    
    ["abc"].pack("P4") => ArgumentError: too short buffer for P(3 for 4)
    [""].pack("P") => ArgumentError: too short buffer for P(0 for 1)
    
  • u

    被uuencode编码的字符串

    [""].pack("u") => ""
    ["a"].pack("u") => "!80``\n"
    ["abc"].pack("u") => "#86)C\n"
    ["abcd"].pack("u") => "$86)C9```\n"
    ["a"*45].pack("u") => "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n"
    ["a"*46].pack("u") => "M86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A86%A\n!80``\n"
    ["abcdefghi"].pack("u6") => "&86)C9&5F\n#9VAI\n"
    
  • U

    utf-8

    [0].pack("U") => "\000"
    [1].pack("U") => "\001"
    [0x7f].pack("U") => "\177"
    [0x80].pack("U") => "\302\200"
    [0x7fffffff].pack("U") => "\375\277\277\277\277\277"
    [0x80000000].pack("U") => ArgumentError
    [0,256,65536].pack("U3") => "\000\304\200\360\220\200\200"
    
    "\000\304\200\360\220\200\200".unpack("U3") => [0, 256, 65536]
    "\000\304\200\360\220\200\200".unpack("U") => [0]
    "\000\304\200\360\220\200\200".unpack("U*") => [0, 256, 65536]
    
  • w

    BER压缩整数

    用7位来表现1字节, 这样就能以最少的字节数来表现任意大小的0以上的整数。各字节的最高位中除了数据的末尾以外,肯定还有个1(也就是说, 最高位可以表示数据伸展到的位置)。

    BER是Basic Encoding Rules的缩略语(BER并非只能处理整数。ASN.1的编码中也用到了它)

  • x

    读入null字节/1字节

  • X

    后退1字节

  • @

    向绝对位置移动

用例

下面是一些pack/unpack的用例。

其实有的问题并不需要使用pack, 但我们还是给了出它的例子。主要是因为pack很容易进行加密, 我们想向不愿使用pack的人提供一点新思路。

  • 将数值(字符代码)的数组变为字符串的例子

    p [82, 117, 98, 121].pack("cccc")
    => "Ruby"
    
    p [82, 117, 98, 121].pack("c4")
    => "Ruby"
    
    p [82, 117, 98, 121].pack("c*")
    => "Ruby"
    
    s = ""
    [82, 117, 98, 121].each {|c| s << c}
    p s
    => "Ruby"
    
    p [82, 117, 98, 121].collect {|c| sprintf "%c", c}.join
    => "Ruby"
    
    p [82, 117, 98, 121].inject("") {|s, c| s << c}
    => "Ruby"
    
  • 将字符串变为数值(字符代码)的数组的例子

    p "Ruby".unpack('C*')
    => [82, 117, 98, 121]
    
    a = []
    "Ruby".each_byte {|c| a << c}
    p a
    => [82, 117, 98, 121]
    
  • 可以用"x"来处理null字节

    p [82, 117, 98, 121].pack("ccxxcc")
    => "Ru\000\000by"
    
  • 可以用"x"来读取字符

    p "Ru\0\0by".unpack('ccxxcc')
    => [82, 117, 98, 121]
    
  • 将Hex dump变为数值数组的例子

    p "61 62 63 64 65 66".delete(' ').to_a.pack('H*').unpack('C*')
    => [97, 98, 99, 100, 101, 102]
    
    p "61 62 63 64 65 66".split.collect {|c| c.hex}
    => [97, 98, 99, 100, 101, 102]
    
  • 在二进制和16进制数的pack中, 指定的长度并不是指生成的字节数, 而是指位或半字节的个数

    p [0b01010010, 0b01110101, 0b01100010, 0b01111001].pack("C4")
    => "Ruby"
    p ["01010010011101010110001001111001"].pack("B32") # 8 bits * 4
    => "Ruby"
    
    p [0x52, 0x75, 0x62, 0x79].pack("C4")
    => "Ruby"
    p ["52756279"].pack("H8")  # 2 nybbles * 4
    => "Ruby"
    
  • 模板字符'a'的长度指定 只适用于一个字符串

    p  ["RUBY", "u", "b", "y"].pack("a4")
    => "RUBY"
    
    p ["RUBY", "u", "b", "y"].pack("aaaa")
    => "Ruby"
    
    p ["RUBY", "u", "b", "y"].pack("a*aaa")
    => "RUBYuby"
    
  • 在模板字符"a"中, 若长度不够时, 就用null字符进行填充

    p ["Ruby"].pack("a8")
    => "Ruby\000\000\000\000"
    
  • 小Endian和大Endian

    p [1,2].pack("s2")
    => "\000\001\000\002" # 在大Endian的系统中的输出
    => "\001\000\002\000" # 在小Endian的系统中的输出
    
    p [1,2].pack("n2")
    => "\000\001\000\002" # 系统无关的大Endian
    
    p [1,2].pack("v2")
    => "\001\000\002\000" # 系统无关的小Endian
    
  • 网络字节顺序的 signed long

    s = "\xff\xff\xff\xfe"
    n = s.unpack("N")[0]
    if n[31] == 1
      n = -((n ^ 0xffff_ffff) + 1)
    end
    p n
    => -2
    
  • 网络字节顺序的 signed long(第2个)

    s = "\xff\xff\xff\xfe"
    p n = s.unpack("N").pack("l").unpack("l")[0]
    => -2
    
  • IP地址

    require 'socket'
    p Socket.gethostbyname("localhost")[3].unpack("C4").join(".")
    => "127.0.0.1"
    
    p "127.0.0.1".split(".").collect {|c| c.to_i}.pack("C4")
    => "\177\000\000\001"
    
  • sockaddr_in 结构体

    require 'socket'
    p [Socket::AF_INET,
       Socket.getservbyname('echo'),
       127, 0, 0, 1].pack("s n C4 x8")
    => "\002\000\000\a\177\000\000\001\000\000\000\000\000\000\000\000"
    

    ruby 1.7 特性: 除了pack/unpack以外, 您还可以使用Socket.pack_sockaddr_in 和 Socket.unpack_sockaddr_in方法。

  • '\0'终点字符串的地址

    模板字符 "p" 和 "P"是为了处理C语言层的接口而存在的(例如ioctl)。

    p ["foo"].pack("p")
    => "8\266\021\010"
    

    结果字符串看起来乱七八糟, 实际上它表示的是字符串"foo\0"的地址(二进制形式)。您可以像下面这样,把它变成您熟悉的形式

    printf "%#010x\n", "8\266\021\010".unpack("L")[0]
    => 0x0811b638
    

    在pack的结果被GC回收之前, 地址所指的对象(在本例中是"foo\0")保证不会被GC所回收.

    您只能使用pack的结果来unpack("p")和unpack("P")。

    p ["foo"].pack("p").unpack("p")
    => ["foo"]
    p "8\266\021\010".unpack("p")
    => -:1:in `unpack': no associated pointer (ArgumentError)
            from -:1
    

    ruby 1.7 特性: "p"和"P"被解释为NULL指针, 它负责对nil进行特殊的处理。(下面是在普通的32bit机器上的结果)

    p [nil].pack("p")        #=> "\000\000\000\000"
    p "\0\0\0\0".unpack("p") #=> [nil]
    
  • 结构体的地址

    例如, 表示

    struct {
      int   a;
      short b;
      long  c;
    } v = {1,2,3};
    

    的字符串是

    v = [1,2,3].pack("i!s!l!")
    

    (考虑到byte alignment的问题, 可能需要进行适当的padding才行)

    您可以使用

    p [v].pack("P")
    => "\300\265\021\010"
    

    来获得指向该结构体的地址。


上一篇:下一篇: