Mae向きなブログ

Mae向きな情報発信を続けていきたいと思います。

インデックスを使った指定行取り出しプログラム(Pure Ruby)

[を]インデックスを使った指定行取り出しプログラム(Pure Perl)Rubyで書き換えてみました。

頭から操作する方法

まずはファイルの頭から操作していくナイーブな方法

コード(getline-naive.rb)
#!/usr/bin/env ruby

qidx = ARGV.shift.to_i          # start from 0
tgtfn = ARGV.shift
f = open(tgtfn)
while line = f.gets
  next if $. != qidx + 1
  print line
  break
end
f.close
実行例:
$ cat test.dic
Japan
Tokyo
Yokohama
This is a pen
Hello World
$ ./getline-naive.rb 2 test.dic
Yokohama

インデックスを使う方法

インデックスを作成するプログラム。

コード(mkidx.rb):
#!/usr/bin/env ruby
ip = 0
while line = gets
  print [ip].pack("N")
  ip += line.length
end
実行例:
$ ./mkidx.rb test.dic > test.dic.ary
$ od -t x1 test.dic.ary
0000000    00  00  00  00  00  00  00  06  00  00  00  0c  00  00  00  15
0000020    00  00  00  23                                                
0000024

インデックスを使った指定行取り出しプログラム。

コード(getline.rb)
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

len_of_N = 4                    # 4で決め打ち

qidx  = ARGV.shift.to_i          # start from 0
tgtfn = ARGV.shift
idxfn = ARGV.shift || tgtfn + ".ary"

tfsz = File.size(tgtfn)
ifsz = File.size(idxfn)
raise if qidx < 0 or qidx * len_of_N >= ifsz

buf = ""

fi = open(idxfn) 
fi.seek(qidx * len_of_N, IO::SEEK_SET)
fi.read(len_of_N, buf)
ixf = buf.unpack("N")[0]
ixt = if fi.pos < ifsz
        fi.read(len_of_N, buf)
        buf.unpack("N")[0]
      else
        tfsz
      end
fi.close

fh = open(tgtfn)
fh.seek(ixf, IO::SEEK_SET)
fh.read(ixt - ixf, buf)
fh.close

print buf
実行例
$ ./getline.rb 2 test.dic
Yokohama