2014-05-01 79 views
1

我需要解压缩打包的ASCII字符的字符串。算法如下:在ruby中更加优雅的打包ASCII算法的实现

  1. 获取3个打包的ASCII字节,将它们放入4个ASCII字节。 (3字节至4字节中的6 + 6 + 6 + 6位)
  2. 对于每个字节,将位6设置为位5的补码。
  3. 对于每个字节将位7复位为零。
  4. 对下3个打包字节重复。

我是新来的Ruby,可能是有解决这个任务更正确,更优雅的方式,而我的代码:

while i < pstr.length 
    parr = [pstr[0] & 0x3F, pstr[0]>>6 | ((pstr[1] << 2) & 0x3F), 
      pstr[1]>>4 | ((pstr[2] << 4) & 0x3F), 
      pstr[2]>>2] 
    parr.collect! { |a| a | (~(a << 1) & 0x20) }   
    parr.collect! { |a| a & 0x7F } 

    puts parr 

    i += 3 
end 

UPDATE1:THX用于收集校正。

+2

只是为了澄清:您的代码按预期工作(例如通过测试),但您希望获得有关Ruby成语或快捷方式的帮助?你可以添加一些测试输入和验证输出到问题,这将有所帮助。 –

+0

你看过'#unpack'吗? http://www.ruby-doc.org/core-2.1.1/String.html#method-i-unpack –

+0

@UriAgassi当我在文档中阅读时,Ruby不支持打包/解压缩打包的ASCII码。 – Darkkey

回答

1

虽然红宝石的Array#packString#unpack不直接支持ASCII包并解压,他们通过pack('m')unpack('m')方式支持Base64编码。这可以帮助解决涉及从每个保存8个相关位的3个字节到每个保存6个4个字节的位移。

这是一个开始的实现packunpack这是一个更红宝石式的。 pack对字符串的操作是4的精确倍数,删除任何余数。相反地​​unpack每3个字符扩大到4

B64 = ('A'..'Z').to_a+('a'..'z').to_a+('0'..'9').to_a+%w(+ /) # Base64 alphabet 
H64 = Hash[B64.zip(0..63)] # Hash character to index 

# Translates every 4 characters to 3, drops any remainder 
def pack(ascii) 
    ascii.bytes.map { |b| B64[b&(b&0x40==0?0x3f:0x1f)] }.join.unpack('m')[0] 
end 

# Translates every 3 characters to 4 
def unpack(bstr) 
    [bstr].pack('m').chomp.split('').map do |c| 
     ((H64[c]|0x40) & (H64[c]&0x20==0?0x5f:0x3f)).chr 
    end.join 
end 

实例:

ascii_packed = pack('Hello World!') 
puts ascii_packed.length # => 9 
puts unpack(ascii_packed) # => "HELLO WORLD!" 

对于那些不熟悉的ASCII包,它是一个 “有损” 压缩。在范围0x20 <= x < 0x60以外的ASCII字符x被翻译成该范围内的字符。这就是为什么小写字母在打包/解包时会大写字母的原因。