pack/unpackの使い方

これまで、Rubyにあるpack/unpackの使い方がいまいちピンと来ずに避けて通って生きてきたんだけど、たまたま見つけたページにサンプルが書かれていたので、それを確かめてみる。

ネタ元は、Rubyでバイナリファイルを一気読み(CoffeeDiary)というエントリ。なぜか<と>の向きが間違っていて、そのままコピペしても使えないので、僕の環境で動いたものを以下に記します。まずはpack/unpackを用いた例。

require 'test/unit'

class ReadTest < Test::Unit::TestCase
  def test_read_write
    data = []
    100000.times do |i|
      data << i
    end

    File.open('read_write.dat','w') do |file|
      file.write data.pack('C*')
    end

    data1 = nil
    data2 = nil
    File.open('read_write.dat') do |file|
      data1 = file.read(10)
      data2 = file.read()
    end

    assert_equal([0,1,2,3,4,5,6,7,8,9],data1.unpack('C*'))
    assert_equal(99990,data2.size)
  end
end

次にpack/unpackを使わない例。

require 'test/unit'

class RadTest < Test::Unit::TestCase

  def test_getc_putc
    data = []
    100000.times do |i|
      data << i
    end

    File.open('getc_putc.dat','w') do |file|
      data.each do |i|
        file.putc i
      end
    end

    data1 = []
    data2 = []
    File.open('getc_putc.dat') do |file|
      10.times do
        data1 << file.getc
      end
      99990.times do |i|
        data2 << i
      end
    end

    assert_equal([0,1,2,3,4,5,6,7,8,9],data1)
    assert_equal(99990,data2.size)
  end
end

記事には、pack/unpackの方が早いって書かれていたので、実際に処理時間をみてみると、

pack/unpackで実行した結果

Loaded suite sample
Started
.
Finished in 0.070109 seconds.

1 tests, 2 assertions, 0 failures, 0 errors

pack/unpackを使わない例

Loaded suite sample2
Started
.
Finished in 0.139087 seconds.

1 tests, 2 assertions, 0 failures, 0 errors

倍ぐらい早さが違う。なんだかこれまで知らなかった僕がもったいなかったなぁ。