Hatena::Grouprubyist

Ruby初心者prinyの学習帳 RSSフィード

2009-01-08練習:たのしいRuby P.285 (1) (2)

練習問題 (1)
あるファイルの内容を別のファイルにそのままコピーするメソッドをを定義しましょう。
このメソッドは、2 つの引数(コピー元のファイル名, コピー先のファイル名)を取ります。

書いたもの

def copy_file(from, to)
  src = open(from)  # コピー元のファイルを開く
  begin
    # コピー先のファイルを開く
    dest = open(to, "w")
    # コピー元のファイルを全部読んで、それをコピー先のファイルに書き込む
    dest.write(src.read)
    dest.close
  rescue  SystemCallError
    $stderr.puts "SystemCallError: #$!"
  rescue
    $stderr.puts "Error: #$!"
  else
    puts "#{from}#{to} にコピーしました。"
  ensure
    src.close
  end
end

copy_file("hello.txt", "copy.txt")

例外処理の項に答えになるサンプルが。

そのままでは何なので、エラーが発生しなかったら、メッセージが表示されるようにしてみた。


練習問題 (2)
Unix で使われる tail コマンドと似たことができるメソッド tail を定義しましょう。
tail メソッドは、2 つの引数(行数, ファイル名)を取ります。

これに、krystalさんの日記へのentottoさんのコメント にある、tail コマンドの -f オプションみたいなものも追加してみよう。
「終了しないで、ファイルが更新されたら、追加された行を表示する」を -f オプションを付けたときだけおこなうようにする方法がわからないので、「指定した行数表示した後、終了しないで、ファイルが更新されたら、追加された行を表示する」という仕様にする。

書いたもの

def tail(line_num, file)
  queue = []
  open(file){|io|
    while line = io.gets
      queue.push(line)
      if queue.size > line_num
        queue.shift
      end
    end
    queue.each{|line| print line }
  
    while true
      io.seek(0, IO::SEEK_CUR)
      if add_line = io.read
        print add_line
      end
      sleep(0.5)
    end
  }
end

tail(3, "hello.txt")

先達の知恵をお借りして、それっぽく動くものができたように思うけど、実際はどうなんだろう。

「ファイルの末尾までデータを読み取ると、それ以上読み込みができなくなるプラットフォームがあって、seek すると(副作用で)EOF フラグが解除される」みたいな記述があったのだけど、「io.seek(0, IO::SEEK_CUR)」をコメントアウトしても、同じ動きをしているように見えるんだよなぁ。

終わらせるときは、[Ctrl]+[C]キーを押す。tail コマンドで -f オプションを付けたときと同じ。

別の話だけど、リアルタイムにログを表示するには、tailf コマンドのほうが tail コマンドより負荷が低いのでよいそうだ。