おことわり

ページの内容上、デリられるかもしれないので各自バックアップしておいてください(ワラ
あとメモ代わりなので文体とか書き方が気持ち悪かったり生理的に受け付けられないかもしれませんがご了承ください。

自鯖にいい書くスペースがなかったので…

Mac OS Xの辞書便利ですね。
New Oxfordとか大辞泉が入ってて、ほんとこの部分はMacすばらしいと思います。
その分Macの値段が高くなってるんだろうけどね。

そんな辞書ですが、残念ながらiPhoneにはないのでした。
EPWING? そんな形式の持ってないです。
広辞苑とか買うお金無いです。
iPhoneでもこの辞書使えたらいいのに。
…ん? 使えるようにすればいいんじゃね?

というわけで

Macの辞書ファイル解析しようぜ。というのがこのページの趣旨です。
もう誰かやってると思うけどね。
"Mac Dictionary Format"でググって10件の中に見つからなかったので自分でやってみます。
辞書ファイルを作る、ならいっぱいあるんですけどね。SDKを解析するのは多分駄目なので。

...http://code.google.com/p/mac-dictionary-kit/なるものを見つけました。
これ独自で作ってるんじゃないか? とすればデータ構造も…

見なかったことにします(ワラ

ファイル構造

以下、解析はMac OS X 10.5(Leopard)で行っています。
Snow Leopardはまた形式が違うかもしれないのでご了承願います。

概略

Macの辞書ファイルは/Library/Dictionaries/以下にあります。
当然のごとくPackageで、

/Library/Dictionaries/
+Apple Dictionary.dictionary
 +Contents
  +Images
   -辞書のページで使う図とか
  +Resources
   (+Language.lproj)
    -一部の辞書は言語別ディレクトリにBody.dataなどがある(例:Apple Dictionary)
  -Info.plist
  -version.plist
  -KeyText.index
  -KeyText.data
  -EntryID.index
  -EntryID.data
  -Body.data
  -cssとか

こんな感じになってます。

Info.plist

使うファイルとかアクセスする手段が書いてあるようです。

KeyText.*

よくわからないですが、索引っぽいです。たぶん。

EntryID.*

よくわかりません。最初こっちが索引かと思いましたが、文字っぽいものが見当たりません。

Body.data

辞書データです。XML形式で、各項目が格納されています。

データ構造

KeyText.index

調べ中

KeyText.data

調べ中(多分索引本体)

EntryID.index

調べ中

EntryID.data

調べ中

Body.data

Info.plistの内容によって難易度が変わります(ワラ

なぜかoffset 0x40から始まります。
最初はデータサイズ(4byte)です。直後から各項目が始まります。

Info.plistでHeapDataCompressionTypeが定義されてないとき

  • 項目のサイズ
  • 項目のサイズ-4
  • 実際の項目

Info.plistでHeapDataCompressionTypeが1の時

  • 項目のサイズ
  • 項目のサイズ-4
  • 展開後のサイズ
  • 実際の項目(zlibでdeflateされている)

zlibでdeflateされているのでzlibヘッダがついています。
78 9cなのでBest compressionなdeflateです。
(なんで78 9cの2バイトでそんなことわかるんだよ、という人は、RFC1950を読みつついろいろなデータを見てください。決まり文句ということがわかります。)
あなたがruby使いならこの形式は以下のスクリプトで展開できると思います。

require 'zlib'

open(ARGV[0],"rb") do |f|
        f.seek(0x40)
        r = f.read(4).unpack("i")[0]
        i = 0
        while true do
                s = f.read(4).unpack("i")[0] # len of data
                t = f.read(4).unpack("i")[0] # len of compd+4?
                u = f.read(4).unpack("i")[0] # len of raw
                v = f.read(s - 8)
                w = Zlib::Inflate.inflate(v)

                puts w

                i += 12 + t
                if i >= r
                        break
                end
        end
end

enjoy!

  • HTML
  • PDF
RSS2.0 RSS1.0 Atom1.0