2013年4月3日水曜日

ruby でファイルダンプ(クラス風味)

ruby のファイルダンププログラムも java で試したクラス風味に変更してみた。ruby でも例外処理の考え方は python と同じ以下の方針と考えました。
Javaとは違い、Pythonの関数は、自身がどのような例外を送出するのかを宣言しない。発生しうる例外のうち捕捉すべきものを見定めるのはあなたの責任だ。
しかし、open エラーの場合、例外が Errno::ENOENT が返却されているので、errno に設定されうる値を全て捕捉しないといけいないのかと悩みました。その後、SystemCallError クラスがあることに気づき、これを rescue することでシステムコールエラーをもれなく捕捉した上で、raise e とすることで詳細情報の引き継ぎもできました。ちょっとしたことに悩むのは相も変わらずです。
#! /usr/bin/ruby
# coding: utf-8

class Dump
  def initialize(file)
    @offset = 0
    begin
      @fp = open(file,"r")
    rescue SystemCallError => e
      raise e
    end
  end

  def address()
    printf("%08x : ",@offset)
  end

  def hexdump(line)
    disp=""
    cnt=0
    line.each_byte do |c|
      if (@cnt == 8) then
          @disp << "- "
      end
      disp << sprintf("%02x ",c)
      cnt+=1
    end
    printf("%-50s ",disp)
  end
  
  def chrdump(line)
    disp="| "
    line.each_byte do |c|
      if ((0x00 <= c and c <= 0x1f) or 0x7f <= c) then
          disp << sprintf(".")
      else
          disp << sprintf("%c",c)
      end
    end
    printf("%-16s\n",disp)
  end

  def isnext()
    return(@fp.eof())
  end

  def next()
    @offset += 16
    return(@fp.read(16))
  end

  def display()
    while(!self.isnext()) 
        self.address()
        line = self.next()
        self.hexdump(line)
        self.chrdump(line)
    end
    @fp.close()
  end
end  

begin
  dump = Dump.new(ARGV.shift)
  dump.display()
rescue SystemCallError => e
  printf("ファイルオープンエラー\n")
  exit(1)
rescue Exception => e
  printf("異常終了\n")
  p e.class,e.backtrace
  exit(2)
end
exit(0)

0 件のコメント:

コメントを投稿