snbhsmt_log

ネットワークとコンピュータ、その他いろいろ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Palm Desktop の Todo データを読む Ruby スクリプト

Palm Desktop の Todo をエクスポートすると出来る *.tda ファイルを Ruby で読んでみた。

tda ファイルのフォーマットは以下のページを参考にしました。
Palm Pilot Desktop Software TODO.DAT and TODO.TDA File Structure
Field Name をそのままハッシュ名に使ってるので、 どこで何を読んでるのかは見れば分ると思います。

tdareader.rb
#!/usr/bin/ruby
# vi: ts=2

# Palm の ToDo データ (todo.dat/*.tda) を読む

$KCODE = 'u'
require 'streamreader'

module Palm
  class Todo
    def self.read_tda(filename)
      sr = StreamReader.new(File.open(filename, 'rb'))
      tda = {}

      tda[:version_tag] = sr.read_n32
      raise "illegal data format" unless tda[:version_tag] == 0x00014454

      tda[:file_name] = sr.read_cstring
      tda[:table_string] = sr.read_cstring
      tda[:next_free] = sr.read_long
      tda[:category_count] = sr.read_long

      tda[:category_entries] = []
      tda[:category_count].times {
        category = {}
        category[:index] = sr.read_long
        category[:id] = sr.read_long
        category[:dirty_flag] = sr.read_long
        category[:long_name] = sr.read_cstring  # カテゴリ名 (full)
        category[:short_name] = sr.read_cstring # カテゴリ名 (8byte)
        tda[:category_entries] << category
      }

      tda[:resource_id] = sr.read_long
      tda[:fields_per_row] = sr.read_long
      tda[:rec_id_pos] = sr.read_long
      tda[:rec_status_pos] = sr.read_long
      tda[:placement_pos] = sr.read_long
      tda[:field_count] = sr.read_short

      tda[:field_entry] = []
      tda[:field_count].times {
        tda[:field_entry] << sr.read_short
      }

      tda[:num_entries] = sr.read_long

      tda[:todo_entry] = []
      (tda[:num_entries] / tda[:field_count]).times {
        todo = {}
        todo[:field_type_1] = sr.read_long
        todo[:record_id] = sr.read_long
        todo[:field_type_2] = sr.read_long
        todo[:status_field] = sr.read_long
        todo[:field_type_3] = sr.read_long
        todo[:position] = sr.read_long
        todo[:field_type_4] = sr.read_long
        todo[:padding_4] = sr.read_long
        todo[:description] = sr.read_cstring # 内容の先頭行
        todo[:field_type_5] = sr.read_long
        todo[:due_date] = sr.read_ulong      # 期日 (1956495599=未指定)
        todo[:field_type_6] = sr.read_long
        todo[:completed] = sr.read_long      # 完了フラグ (1=完了)
        todo[:field_type_7] = sr.read_long
        todo[:priority] = sr.read_long       # プライオリティ (1..5)
        todo[:field_type_8] = sr.read_long
        todo[:private] = sr.read_long        # プライベートフラグ (1=private)
        todo[:field_type_9] = sr.read_long
        todo[:category] = sr.read_long       # カテゴリのindex+1 (0=未分類)
        todo[:field_type_10] = sr.read_long
        todo[:padding_10] = sr.read_long
        todo[:note] = sr.read_cstring        # 内容
        tda[:todo_entry] << todo
      }

      sr.close
      tda
    end
  end # class Todo
end

if $0 == __FILE__
  require 'kconv'
  require 'pp'

  filename = ARGV.shift || exit(63)
  tda = Palm::Todo.read_tda(filename)

  #$KCODE = 's'
  #pp tda

  ## カテゴリ名の参照
  #category = tda[:category_entries]
  #todolist = tda[:todo_entry]
  #index = todolist[0][:category]
  #p index == 0 ? "未分類" : category[index-1][:long_name].toutf8

  # 全todo の description を表示
  tda[:todo_entry].each { |todo|
    puts todo[:description].toutf8
  }
end

streamreader.rb
#!/usr/bin/ruby
# vi: ts=2

# StreamReader : File とか StringIO を先頭から順番に読む

$KCODE = 'u'

class StreamReader
  def initialize(stream)
    raise "not readable object" unless stream.respond_to?(:read)
    @f = stream
  end

  def close
    @f.close if @f != nil && @f.respond_to?(:close)
  end

  def read_byte; @f.read(1).unpack('c')[0] end
  def read_ubyte; @f.read(1).unpack('C')[0] end
  def read_short; @f.read(2).unpack('s')[0] end
  def read_ushort; @f.read(2).unpack('S')[0] end
  def read_long; @f.read(4).unpack('l')[0] end
  def read_ulong; @f.read(4).unpack('L')[0] end
  def read_n32; @f.read(4).unpack('N')[0] end
  def read_string(len); @f.read(len) end
  def read_cstring
    len = read_ubyte
    len = read_ushort if len == 255
    read_string(len)
  end
end

if $0 ==  __FILE__
  require 'stringio'

  filename = ARGV.shift || exit(63)
  sr = StreamReader.new(File.open(filename, 'rb'))
  puts sr.read_byte.chr
  sr.close

  buf = File.open(filename, 'rb').read
  sr = StreamReader.new(StringIO.open(buf, 'r'))
  puts sr.read_byte.chr
  sr.close
end
スポンサーサイト

« Palm Desktop の予定データを読む Ruby スクリプト|Top|Hpricot をインストールしようとしてエラー »

コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://snbhsmt.blog110.fc2.com/tb.php/112-fc05cfc8

Top

HOME

Author:snbhsmt
Google Profiles

http://www.ksky.ne.jp/~snbhsmt/

全ての記事を表示する

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。