以下、本実施の形態を図面を参照して説明する。
[第1の実施の形態]
図1は、第1の実施の形態の情報処理装置を示す図である。
情報処理装置10は、圧縮データ11を伸長して伸長データ12を生成し、また、伸長データ12に対応するインデックス13を生成する。圧縮データ11は、例えば、ハフマン符号を用いて圧縮されたZIPファイルである。伸長データ12は、例えば、電子化された小説や学術書や辞書などの電子書籍のファイルである。インデックス13は、例えば、伸長データ12に対する全文検索に用いられる。情報処理装置10は、電子書籍リーダや電子辞書や携帯電話機などの情報端末装置であってもよいし、デスクトップコンピュータやサーバコンピュータなどの据え置き型装置であってもよい。
情報処理装置10は、記憶部14と伸長部15を有する。記憶部14は、圧縮データを伸長するときに参照される辞書データ14aを記憶する。記憶部14は、RAMなどの揮発性記憶装置でもよいし、フラッシュメモリやHDD(Hard Disk Drive)などの不揮発性記憶装置でもよい。伸長部15は、辞書データ14aを参照して圧縮データ11を伸長し、伸長データ12とインデックス13を生成する。伸長部15は、CPU(Central Processing Unit)やDSP(Digital Signal Processor)などのプロセッサを含んでもよく、ASIC(Application Specific Integrated Circuit)やFPGA(Field-Programmable Gate Array)などの電子回路を含んでもよい。メモリに格納したプログラムをプロセッサが実行することで以下の処理が実現されるとき、情報処理装置10はコンピュータと言うことができる。
インデックス13は、伸長データ12に含まれ得る複数の記号それぞれに対応するフラグ情報を含み、伸長データ12に各記号が含まれているか否かをフラグ情報によって示している。各記号に対応するフラグ情報は、例えば、その記号が出現するか否かを示す少なくとも1つのフラグを含む。フラグは、例えば、1ビットで表現され、その記号が出現するときは“1”に設定され出現しないときは“0”に設定される。辞書データ14aは、圧縮に用いられる符号と関連付けて、その符号に対応する記号と、インデックス13内においてその記号に対応するフラグ情報を識別するための識別情報とを含む。辞書データ14aは、圧縮データ11を伸長するときに、伸長部15が生成するようにしてもよい。
伸長部15は、圧縮データ11を伸長するとき、辞書データ14aから、圧縮データ11に含まれる符号に関連付けられている記号(復号した記号)と識別情報とを取得する。そして、伸長部15は、辞書データ14aから取得した記号を用いて伸長データ12を生成する。例えば、伸長部15は、伸長結果としての記号列を格納するバッファの末尾に、取得した記号を格納する。また、伸長部15は、インデックス13のフラグ情報のうち、辞書データ14aから取得した識別情報が示すフラグ情報を更新する。例えば、伸長部15は、識別情報が示すフラグ情報に含まれるフラグを“1”に設定する。
例えば、辞書データ14aに、ある符号に関連付けて、復号した記号tと識別情報0x1D(10進数で29)が登録されているとする。圧縮データ11からその符号を取得すると、伸長部15は、伸長データ12としての記号列に記号tを追加し、また、識別情報0x1Dが指し示すインデックス13内のフラグ情報を更新する。辞書データ14aに識別情報が登録されているため、伸長部15は、伸長結果を格納するバッファから記号tを読み直してインデックス13の中から記号tに対応するフラグ情報を探さなくてよい。
なお、伸長データ12やインデックス13における「記号」は、1つの文字でもよいし1バイトのビット列でもよい。1つの文字が2バイト以上で表現されるとき、その文字は複数の「記号」に分割されることがある。また、インデックス13は、N個(Nは2以上の整数)の記号を含む記号列に対応するフラグ情報を含んでもよい。N=2の記号列はバイグラム(bi-gram)、N=3の記号列はトライグラム(tri-gram)と呼ぶことがある。その場合、伸長部15は、例えば、伸長が完了した直近のN−1個の記号に対応する識別情報を、メモリなどの記憶装置に一時的に保存しておく。そして、伸長部15は、次に辞書データ14aから取得した識別情報と保存してあるN−1個の記号分の識別情報との組み合わせによって、インデックス13の中から記号列に対応するフラグ情報を特定する。
また、各記号または記号列に対応するフラグ情報は、伸長データ12を分割した所定の単位毎に、当該単位のデータ内にその記号または記号列が含まれているか否かを示すフラグを含んでもよい。所定の単位は、例えば、ファイル、ファイル内の項目、所定長(例えば、256バイト、512バイト、1024バイトなど)のブロックなどである。伸長部15は、伸長データ12の種類(例えば、小説や辞書など)を判定し、判定した種類に応じて、ファイル・項目・ブロックなどの複数の単位の中から、フラグを作成する単位を選択するようにしてもよい。また、ブロック毎にフラグを作成する場合であって、2つのブロックに跨がる記号列が存在するとき、伸長部15は、2つのブロックの両方がその記号列を含んでいることを示すように、その記号列に対応するフラグ情報を更新してもよい。
第1の実施の形態の情報処理装置10によれば、復号した記号に対応するフラグ情報の識別情報が辞書データ14aに登録されているため、伸長データ12の生成と並行して、伸長データ12に対応するインデックス13を効率的に生成できる。すなわち、圧縮データ11の伸長が完了してから、伸長結果を格納するバッファから各記号を取得してインデックス13内の更新するフラグ情報を探す方法では、伸長データ12やインデックス13を記憶するRAMなどの記憶装置へのアクセスが多くなってしまう。これに対し、辞書データ14aに登録された識別情報を用いて、インデックス13内の所望のフラグ情報に直接アクセスすることで、記憶装置へのアクセスを減らすことができる。また、圧縮データ11の伸長が完了した時点で、伸長データ12に対応するインデックス13が生成されているため、伸長データ12に対する検索をすぐに開始することが可能となる。
[第2の実施の形態]
図2は、情報端末装置のハードウェア例を示すブロック図である。
情報端末装置100は、ユーザの操作に応じて、電子化された小説や学術書や辞書などの電子書籍を表示することができる情報端末装置である。電子書籍は、ハフマン符号を用いて圧縮されたZIPファイルとして配布される。電子書籍のフォーマットとしては、IDPF(International Digital Publishing Forum)が標準化を進めるEPUB(Electronic Publication)やXMDF(ever-Extending Mobile Document Format)などが挙げられる。電子書籍ファイルは、例えば、本文を記載したXHTML(Extensible HyperText Markup Language)ファイルや、表示方法を定義したCSS(Cascading Style Sheets)ファイルや、図形を表したSVG(Scalable Vector Graphics)ファイルを含む。
情報端末装置100は、CPU101、RAM102、不揮発性メモリ103、ディスプレイ104、入力部105、カードリーダ106および無線通信部107を有する。なお、情報端末装置100は、第1の実施の形態の情報処理装置10の一例である。RAM102や不揮発性メモリ103は第1の実施の形態の記憶部14の一例であり、CPU101は第1の実施の形態の伸長部15の一例である。
CPU101は、プログラムの命令を実行する演算器を含むプロセッサである。CPU101は、不揮発性メモリ103に記憶されているプログラムやデータの少なくとも一部をRAM102にロードし、プログラムを実行する。なお、CPU101は複数のプロセッサコアを備えてもよく、情報端末装置100は複数のプロセッサを備えてもよく、以下で説明する処理を複数のプロセッサまたはプロセッサコアを用いて並列実行してもよい。
RAM102は、CPU101が実行するプログラムや情報処理に用いられるデータを一時的に記憶する揮発性メモリである。なお、情報端末装置100は、RAM以外の種類のメモリを備えてもよく、複数のメモリを備えてもよい。
不揮発性メモリ103は、OS(Operating System)やファームウェアやアプリケーションソフトウェアなどのソフトウェアのプログラム、および、ZIPファイルなどのデータを記憶する記憶装置である。不揮発性メモリ103は、例えば、フラッシュメモリである。なお、情報端末装置100は、HDDなどの他の種類の不揮発性記憶装置を備えてもよく、複数の不揮発性記憶装置を備えてもよい。
ディスプレイ104は、CPU101からの命令に従って、電子書籍を選択するための操作画面や選択された電子書籍のデータなどを表示する。ディスプレイ104としては、例えば、液晶ディスプレイ(LCD:Liquid Crystal Display)や有機EL(Electro-Luminescence)ディスプレイなどを用いることができる。
入力部105は、ユーザの入力操作を検知し、押下されたボタンやタッチ位置などを示す入力信号をCPU101に出力する。入力部105としては、例えば、1またはそれ以上のボタンを備えるキーパッドや、タッチ位置を検出できるタッチパネルなどを用いることができる。情報端末装置100は、複数の種類の入力デバイスを備えてもよい。
カードリーダ106は、カード型の可搬記録媒体である記録媒体21に記録されたプログラムやデータを読み取る駆動装置(ドライブ)である。カードリーダ106は、CPU101からの命令に従って、記録媒体21から読み出したプログラムやデータをRAM102または不揮発性メモリ103に格納する。記録媒体21は、例えば、microSD(Secure Digital)メモリやフラッシュメモリなどの不揮発性の半導体メモリである。ただし、情報端末装置100は、ディスク型の可搬記録媒体に記録されたプログラムやデータを読み取るディスクドライブを備えてもよい。その場合、記録媒体21として、例えば、フレキシブルディスク(FD:Flexible Disk)などの磁気ディスク、CD(Compact Disc)やDVD(Digital Versatile Disc)などの光ディスク、光磁気ディスク(MO:Magneto-Optical disk)などを使用できる。
無線通信部107は、携帯電話網や無線LAN(Local Area Network)などの無線アクセス網に接続して無線通信を行う通信インタフェースである。無線通信部107は、無線アクセス網に属するアクセスポイント22(基地局と呼ぶこともある)と無線通信する。無線通信部107は、アクセスポイント22を介してサーバコンピュータから、プログラムやデータを受信し、RAM102または不揮発性メモリ103に格納する。なお、情報端末装置100は、有線の通信インタフェースを備えてもよい。
情報端末装置100は、電子書籍として、記録媒体21に記録されて配布されたZIPファイルやネットワーク経由で配布されたZIPファイルを、不揮発性メモリ103に格納する。そして、情報端末装置100は、ユーザが指定したZIPファイルを不揮発性メモリ103からRAM102にロードし、ZIPファイルをRAM102上で伸長して、伸長したデータをディスプレイ104に表示する。電子書籍としてのZIPファイルは、DRM(Digital Rights Management)によって複製が制限されていることがある。情報端末装置100は、電子書籍のデータをディスプレイ104に表示する毎にZIPファイルを伸長し、伸長したデータを不揮発性メモリ103に保存しないことが好ましい。
図3は、ファイルと項目とブロックの関係を示す図である。不揮発性メモリ103に、圧縮された複数のZIPファイルが格納され得る。各ZIPファイルを伸長して得られるテキストファイル(例えば、XHTMLファイル)には、複数の項目が含まれ得る。項目は、例えば、電子書籍の小説や学術書における1つの章や節、電子辞書における1つの見出し語分の記載に相当する。また、伸長されたテキストファイルは、所定のバイト数(例えば、256バイト、512バイト、1024バイトなど)のブロックに分割され得る。1つの項目(例えば、サイズの大きい項目)は、複数のブロックを含むことがある。
図4は、インデックスのデータ構造例を示す図である。
情報端末装置100は、ユーザが入力したキーワードを含む可能性のあるファイル、項目またはブロックを検索できるよう、インデックスを生成し、インデックスファイルを不揮発性メモリ103に格納する。不揮発性メモリ103に格納されたインデックスファイルを用いることで、情報端末装置100は、各ZIPファイルを伸長する前に、伸長するZIPファイルを絞り込むことができる。1つのインデックスファイルは、ZIPファイル毎に生成されてもよいし、複数のZIPファイル分のインデックスを含んでもよい。
インデックスは、伸長したファイルに出現し得る1グラム(ユニグラム)の記号、2グラム(バイグラム)の記号列および3グラム(トライグラム)の記号列それぞれについてのビットマップを含む。第2の実施の形態では、「記号」として1バイト記号を考える。各記号は、0x00〜0xFF(10進数で0〜255)の範囲の値を取る。インデックスは、最大で、1グラムに関する256個のビットマップと、2グラムに関する65536個のビットマップと、3グラムに関する16777216個のビットマップを含む。
1グラムのビットマップは、ビットマップIDによって識別される。例えば、ビットマップIDを、1グラムのビットマップを記憶する領域の先頭からのオフセットとして用いることで、そのビットマップの位置を示すアドレスが算出される。2グラムのビットマップは、1グラムに関する2つのビットマップIDの組み合わせよって識別される。例えば、記号列0x0001に対応するビットマップは、記号0x00のビットマップIDと記号0x01のビットマップIDの組み合わせによって識別される。例えば、2つのビットマップIDを結合して得られる値を、2グラムのビットマップを記憶する領域の先頭からのオフセットとして用いることで、アドレスが算出される。3グラムのビットマップは、1グラムに関する3つのビットマップIDの組み合わせによって識別される。
各ビットマップは、複数の単位(ファイル、項目またはブロック)に対応する複数のビットを含む。ビット=1は記号または記号列が出現することを示し、ビット=0は記号または記号列が出現しないことを示す。第2の実施の形態のビットマップは、第1の実施の形態で述べたフラグ情報の一例である。図4に示すように、以下の第2の実施の形態の説明では、ビットマップが各ブロックに対応するビットを含んでいる場合を考える。
図5は、圧縮ファイルのデータ構造例を示す図である。第2の実施の形態の圧縮および伸長では、1バイト(8ビット)の記号を最小単位とし、各記号を0x00〜0xFFの範囲の数値として扱う。2バイト文字や3バイト文字など複数バイトで表される文字は、文字単位で扱わずに複数の1バイト記号の列として扱うこととする。
ZIPファイルの圧縮には、LZ77アルゴリズムとハフマン符号化とを組み合わせた可逆圧縮アルゴリズムが用いられる。データの圧縮では、64kバイト(または、所定のバイト数)のスライド窓の記号列を利用して、以下の処理を行う。まず、64kバイトの記号列における0x00〜0xFFの各記号の出現頻度を算出し、ハフマン木を生成して各記号に対応する符号を決定する。そして、64kバイトの記号列の先頭から末尾に向かって圧縮を進める。
現在着目している記号を先頭とする記号列であって、長さ3バイト以上の記号列が既出であるとき、その記号列を、一致した記号列の「バイト数」と先に出現した同じ記号列の「先頭アドレス」とに変換する。バイト数は、生成したハフマン木に従ってハフマン符号化される。先頭アドレスは、MSB(Most Significant Bit)から数えて最初にビット=1が現れる桁を示す数値とその桁より後ろにある残りのビット列とに分解され、桁を示す数値がハフマン符号化されて残りのビット列と結合される。一方、現在着目している記号を先頭とする記号列が上記の条件を満たさないとき、現在着目している1バイト記号をハフマン符号化する。なお、圧縮アルゴリズムについては、次の書籍にも記載されている:植松友彦,「文字データ圧縮アルゴリズム入門」,1994年。
情報端末装置100が取得するZIPファイルは、圧縮前の64kバイトの記号列毎に生成された、図5に示すような構造の圧縮データを含む。圧縮データは、ヘッダ部と符号語部とを含む。ヘッダ部は、ハフマン符号化において、0x00〜0xFFの256通りの記号それぞれが何ビットの符号に符号化されているかを示している。各符号の長さは1ビット以上16ビット以下であり、符号長は4ビットで表現できる。情報端末装置100は、ヘッダ部に基づいて、圧縮に用いられたハフマン木を再現することができる。
符号語部は、複数の符号語を含む。各符号語の先頭ビットは制御用のビットである。先頭ビット=0に続く符号語には、ハフマン符号化した1バイト記号が含まれる。ハフマン符号化した1バイト記号の長さは可変長(Naビット)であり、1ビット以上16ビット以下である。先頭ビット=0に続く符号語は、ハフマン木に従って抽出し、1バイト記号に変換することで復号できる。先頭ビット=1に続く符号語には、ハフマン符号化したバイト数と、上記のように変則的な符号化を行った先頭アドレスとが含まれる。ハフマン符号化したバイト数の長さは可変長(Nlビット)であり、符号化した先頭アドレスは可変長である(Npビット)。先頭ビット=1に続く符号語からは、ハフマン木に従った復号と伸長済の先の記号列からの複製とによって、3バイト以上の記号列を復号できる。
図6は、スライド窓を用いた圧縮ファイルの伸長例を示す図である。情報端末装置100は、ZIPファイル内の圧縮データを伸長するとき、符号語部に含まれる符号語の列を格納するバッファと伸長した記号列を格納するバッファを、RAM102に確保する。情報端末装置100は、伸長した記号列のうち直近の8kバイト(または、2kバイトや4kバイトなど所定長)の記号列を、スライド窓に含まれる記号列として取り扱う。前述の「先頭アドレス」は、スライド窓内での位置を示すアドレスである。
情報端末装置100は、符号語の先頭ビット=1のとき、その先頭ビットに続く「バイト数」を復号し、更にバイト数に続く「先頭アドレス」を復号する。そして、情報端末装置100は、先頭アドレスとバイト数からスライド窓内の範囲を特定し、伸長した記号列を格納するバッファの末尾に、特定した範囲にある記号列を複製する。例えば、先頭アドレスが示す位置から後方に向かってabcdefgh・・・という記号列がスライド窓に含まれており、バイト数=4である場合、記号列abcdがバッファの末尾に追加される。一方、情報端末装置100は、符号語の先頭ビット=0のとき、その先頭ビットに続く1バイト記号を復号してバッファの末尾に追加する。その後、情報端末装置100は、バッファに追加した記号の数だけスライド窓を後方にシフトする。
図7は、二分ハフマン木の例を示す図である。情報端末装置100は、ZIPファイルのヘッダ部に記載された複数の記号それぞれの符号長に基づいて、圧縮に用いられた二分ハフマン木を再現する。図7に示したハフマン木の例では、説明を簡単にするため、元のデータに8通りの記号0x00〜0x07のみが含まれる場合を考えている。
情報端末装置100は、記号0x00〜0xFF(図7の例では0x00〜0x07)を、ハフマン符号化したときの符号長の小さい順に並べる。符号長が同じになる複数の記号は、数値の小さい順に並べる。例えば、記号0x01が符号長=1、記号0x02が符号長=2、記号0x00,0x04,0x06が符号長=4、記号0x03が符号長=5、記号0x05,0x07が符号長=6とする。この場合、8個の記号を0x01,0x02,0x00,0x04,0x06,0x03,0x05,0x07の順に並べる。
また、情報端末装置100は、符号長から各記号の出現頻度を推定する。出現頻度(出現確率)は、例えば、符号長をLとすると1/2Lと算出できる。そして、情報端末装置100は、上記のように並べた記号の順序を維持して、各記号の出現頻度に基づいてハフマン木を生成する。すなわち、まず各記号に対応する葉ノードを生成し、出現頻度の小さい方から2つのノード(葉ノードまたは中間ノード)を選択して新たな中間ノードを生成することを繰り返す。例えば、図7の例では、出現頻度が1/26である2つの葉ノード(0x05,0x07)を結合して出現確率が1/25である中間ノードを生成し、この中間ノードと出現確率が1/25である葉ノード(0x03)を結合する。
このようにハフマン木を生成すると、左側(図7では上側)の葉ノードほど深さが小さく、右側(図7では下側)の葉ノードほど深さが大きいハフマン木が生成される。情報端末装置100は、分岐毎に左側の枝に“0”を割り当てて右側の枝に“1”を割り当てる(または、その逆を割り当てる)。そして、情報端末装置100は、ルートノードから各葉ノードに向かって枝を辿ることで、各記号を符号化したときの符号を判定できる。例えば、記号0x00は符号0と対応付けられ、記号0x02は符号10と対応付けられる。以上のように、情報端末装置100は、複数の記号を符号長の小さい順に並べ、符号長が同じになる記号は数値の小さい順に並べるというルールを、圧縮を行う装置と合意しておくことで、記号毎の符号長からハフマン木を一意に生成することができる。
図8は、情報端末装置で動作するソフトウェア例を示すブロック図である。不揮発性メモリ103に、圧縮ファイル111とインデックスファイル112が格納される。また、情報端末装置100は、バッファ部120、ファイルアクセス部131、伸長部132、ハフマン木生成部133、ハフマン木記憶部134、表示制御部135および検索部136を有する。バッファ部120およびハフマン木記憶部134は、例えば、RAM102に確保した記憶領域として実現される。ファイルアクセス部131、伸長部132、ハフマン木生成部133、表示制御部135および検索部136は、例えば、RAM102にロードされCPU101により実行されるプログラムのモジュールとして実現される。
圧縮ファイル111は、ハフマン符号を用いて圧縮された、電子書籍としてのZIPファイルである。圧縮ファイル111は、記録媒体21から読み込まれ、または、アクセスポイント22から受信されて、不揮発性メモリ103に格納されている。インデックスファイル112は、圧縮ファイル111を含む1またはそれ以上の圧縮ファイルについてのインデックスを含む。圧縮ファイル111についてのインデックスは、圧縮ファイル111を最初に伸長するときに生成されて、インデックスファイル112に登録される。
バッファ部120は、バッファ121,122、スタック123およびインデックス124を含む。バッファ121は、伸長結果としての記号列を一時的に記憶する64kバイトの記憶領域である。バッファ122は、バッファ121に記憶された各記号に対応するビットマップIDを記憶する記憶領域である。スタック123は、バッファ122の末尾に記憶されたビットマップID(1つ前の記号に対応するビットマップID)と、バッファ122の最後から2番目に記憶されたビットマップID(2つ前の記号に対応するビットマップID)を記憶する記憶領域である。インデックス124は、図4に示した構造のビットマップの集合であり、インデックスファイル112に登録される。
ファイルアクセス部131は、ユーザの入力操作によって電子書籍が選択されると、選択された電子書籍に対応する圧縮ファイル111を不揮発性メモリ103から読み込み、伸長部132に渡す。なお、圧縮ファイル111の伸長は、圧縮ファイル111全体をRAM102に読み込んでから開始してもよいし、読み込みが完了する前に読み込み済の部分に対して開始してもよい。また、ファイルアクセス部131は、伸長部132によって生成されたインデックス124を、インデックスファイル112に登録する。
伸長部132は、圧縮ファイル111に含まれる1組のヘッダ部と符号語部を単位として伸長処理を行う。伸長部132は、ヘッダ部に記載された各記号の符号長をハフマン木生成部133に通知して、ハフマン木の構造体データの生成を指示する。そして、伸長部132は、ハフマン木記憶部134に記憶されたハフマン木の構造体を参照して、符号語部に含まれる複数の符号語を先頭から順に伸長し、伸長した記号をバッファ121に格納していく。また、伸長部132は、伸長の進行に合わせてスライド窓の位置を制御する。
また、伸長部132は、圧縮ファイル111から記号が伸長される毎に、インデックス124のビットマップを更新していく。伸長部132は、今回伸長した記号に対応するビットマップIDを判定し、そのビットマップIDによって特定される1グラムのビットマップを更新する。また、伸長部132は、今回のビットマップIDとスタック123に記憶された1つ前のビットマップIDとによって特定される2グラムのビットマップを更新する。また、伸長部132は、今回のビットマップIDとスタック123に記憶された1つ前および2つ前のビットマップIDとによって特定される3グラムのビットマップを更新する。また、伸長部132は、今回のビットマップIDをバッファ122に格納し、スタック123に記憶された1つ前および2つ前のビットマップIDを書き換える。
ハフマン木生成部133は、伸長部132から記号0x00〜0xFFそれぞれを符号化したときの符号長の情報を取得し、符号長に基づいて複数の記号を並べ替え、図7のような構造のハフマン木を生成する。そして、ハフマン木生成部133は、生成したハフマン木を表した構造体データを、ハフマン木記憶部134に格納する。
ハフマン木記憶部134は、ハフマン木生成部133が生成したハフマン木の構造体データを記憶する。ハフマン木の構造体データは、64kバイトの記号列が伸長される毎に更新され得る。構造体データは、後述するように、圧縮に用いられる符号と関連付けて、その符号を復号した記号と、その記号に対応するビットマップIDを含む。伸長部132は、圧縮ファイル111の符号語部からビット列を抽出し、抽出したビット列(符号)に関連付けられている記号とビットマップIDを構造体データから取得することになる。
表示制御部135は、バッファ121から伸長済の64kバイトの記号列を取得する。例えば、表示制御部135は、バッファ121が満杯になる毎に、バッファ121に記憶された記号列をRAM102の他の記憶領域に移動する。そして、表示制御部135は、圧縮ファイル111の伸長が完了すると、伸長データから電子書籍の表示画面を生成し、ディスプレイ104に表示させる。例えば、表示制御部135は、伸長データに含まれるXHTMLファイルやSVGファイルに基づいて、テキストや図形を含むページをレンダリングし、電子書籍の内容をページ単位でディスプレイ104に表示する。
検索部136は、入力部105を用いてユーザが入力したキーワードを取得し、インデックス124を参照して、そのキーワードを含む可能性のあるブロックを検索する。そして、検索部136は、検索されたブロックを含むページを表示するよう、表示制御部135に指示する。ただし、前述のように、検索する単位は項目やファイルであってもよい。
ここで、1グラム・2グラム・3グラムのビットマップを用いてブロックを検索する方法の一例を説明する。検索部136は、入力されたキーワードを、種類が同じである連続する文字の列(1文字の場合も含む)毎に分割する。文字の種類としては、例えば、英数字などの1バイトで表される文字、2バイトで表される文字、3バイトで表される文字、4バイトで表される文字などが挙げられる。検索部136は、1バイト文字1つから成る文字列からは1グラムを1個生成し、1バイト文字2つから成る文字列からは2グラムを1個生成し、1バイト文字s個(sは3以上の整数)から成る文字列からは3グラムをs−2個生成する。また、検索部136は、2バイト文字から成る文字列からは文字毎に2グラムを生成し、3バイト文字から成る文字列からは文字毎に3グラムを生成し、4バイト文字から成る文字列からは文字毎に2グラムを2個生成する。
そして、検索部136は、キーワードから生成した1グラム・2グラム・3グラムそれぞれに対応するビットマップをインデックス124から取得し、複数のビットマップの間で、ビット毎の論理積(AND)を計算する。検索部136は、論理積の結果においてビット=1となっているブロックを、キーワードを含む可能性のあるブロックと判定する。ただし、上記の検索方法は一例であり、インデックス124に含まれる1グラム・2グラム・3グラムのビットマップの利用方法は、これに限定されない。
なお、伸長部132は、圧縮ファイル111を初めて伸長するときに、圧縮ファイル111に対応するインデックス124を生成してインデックスファイル112に登録すればよい。伸長部132は、例えば、圧縮ファイル111を伸長するとき、圧縮ファイル111に対応するインデックスがインデックスファイル112に登録済であるか確認し、登録済であればインデックス124を生成しなくてもよい。なお、圧縮ファイル111は、第1の実施の形態の圧縮データ11の一例である。インデックス124は、第1の実施の形態のインデックス13の一例である。ハフマン木記憶部134に記憶された構造体データは、第1の実施の形態の記憶部14に記憶された辞書データ14aの一例である。
図9は、ハフマン木を表した構造体データの第1の例を示す図である。図9に示すような構造体データが、ハフマン木生成部133によって生成されてハフマン木記憶部134に格納される。図9に記載した1行は、2バイトの記憶領域に相当する。
ハフマン木の構造体データは、ヘッダ領域および枝・葉領域を含む。ヘッダ領域には、構造体データのサイズや枝・葉領域の先頭アドレスなど、管理用の情報が格納される。枝・葉領域には、ハフマン木のルートノードおよび中間ノードそれぞれに対して、4バイト(2行)の記憶領域が割り当てられる。4バイトのうちの前半2バイト(前半1行)は左子ノードを辿る枝に相当し、4バイトのうちの後半2バイト(後半1行)は右子ノードを辿る枝に相当する。枝・葉領域の先頭4バイトは、ルートノードに割り当てられる。
左子ノードを辿る枝および右子ノードを辿る枝に相当する2バイトの記憶領域それぞれには、生成されたハフマン木に応じて、ポインタと葉データの何れか一方が格納される。ポインタは、子ノードが中間ノードであることを示しており、子ノードに割り当てられた記憶領域の先頭アドレスを含む。葉データは、子ノードが葉ノードであることを示しており、元の記号(伸長記号)と伸長記号に対応するビットマップIDとを含む。ポインタの先頭ビットは“0”に設定され、葉データの先頭ビットは“1”に設定されている。
ハフマン符号を復号するとき、伸長部132は、圧縮データから1ビットを抽出し、抽出したビットを枝・葉領域の先頭位置からのオフセットとして用いて、ルートノードの左子ノードを辿る枝または右子ノードを辿る枝に相当するデータを選択する。すなわち、伸長部132は、圧縮データから抽出したビットが“0”のときは左子ノードを辿り、圧縮データから抽出したビットが“1”のときは右子ノードを辿ることになる。伸長部132は、選択したデータの先頭ビットを確認し、先頭ビットが“1”のときは、選択したデータ(すなわち、葉データ)から伸長記号とビットマップIDを取得する。
一方、伸長部132は、先頭ビットが“0”のときは、選択したデータ(すなわち、ポインタ)からアドレスを取得すると共に、圧縮データから次の1ビットを抽出する。伸長部132は、抽出したビットを、取得したアドレスが示す位置からのオフセットとして用いて、中間ノードの左子ノードまたは右子ノードを辿る。伸長部132は、何れかの葉データに到達するまでポインタを辿ることを繰り返すことで、符号を復号できる。
図10は、ファイル伸長の第1の手順例を示すフローチャートである。
(ステップS11)ハフマン木生成部133は、圧縮ファイル111のヘッダ部に記載された記号0x00〜0xFFそれぞれの符号長に基づいて、ハフマン木の構造体データをハフマン木記憶部134上に生成する。構造体データの生成方法の詳細は後述する。
(ステップS12)伸長部132は、次に伸長する符号語の先頭ビットを確認し、先頭ビット=0であるか判断する。符号語の先頭ビット=0の場合、処理をステップS13に進める。符号語の先頭ビット=1の場合、処理をステップS15に進める。
(ステップS13)伸長部132は、ハフマン木記憶部134に記憶された構造体データを参照して、符号語の先頭ビットの後ろに存在するハフマン符号化された1バイト記号を復号する。また、伸長部132は、1バイト記号の復号と併せて、構造体データを参照して、復号された1バイト記号に対応するビットマップを識別するためのビットマップIDを特定する。構造体データを用いたハフマン復号の詳細は後述する。
(ステップS14)伸長部132は、ステップS13で復号した記号をバッファ121の末尾に追加する。また、伸長部132は、ステップS13で特定したビットマップIDをバッファ122の末尾に追加する。そして、処理を後述するステップS21に進める。
(ステップS15)伸長部132は、ハフマン木記憶部134に記憶された構造体データを参照して、符号語の先頭ビットの後ろに存在するハフマン符号化された「バイト数」を復号する。構造体データを用いたハフマン復号の詳細は後述する。
(ステップS16)伸長部132は、ハフマン木記憶部134に記憶された構造体データを参照して、ステップS15で復号された符号の後ろに存在するハフマン符号化された「桁数」を復号する。構造体データを用いたハフマン復号の詳細は後述する。
(ステップS17)伸長部132は、ステップS16で復号した「桁数」がMSBから数えて最初にビット=1が現れる桁を意味するように、「先頭アドレス」の上位のビット列を算出する。また、伸長部132は、「先頭アドレス」の残りのビット数を算出し、残りのビット数分のビット列を、ステップS16で復号された符号の後ろから抽出する。そして、伸長部132は、上位と下位のビット列を結合して「先頭アドレス」を復元する。
(ステップS18)伸長部132は、スライド窓に含まれる伸長済の記号列の中から、ステップS15で復号した「バイト数」とステップS17で復元した「先頭アドレス」とによって特定される3バイト以上の記号列を取得する。そして、伸長部132は、取得した記号列をバッファ121の末尾に複製する。また、伸長部132は、記号列に対応するビットマップIDの列をバッファ122から取得し、バッファ122の末尾に複製する。
図11は、ファイル伸長の第1の手順例を示すフローチャート(続き)である。
(ステップS21)伸長部132は、ステップS13またはステップS18で取得した1またはそれ以上のビットマップIDから、先頭に近い順に1つビットマップIDを選択する。伸長部132は、選択したビットマップIDを、1グラムの領域の先頭からのオフセットとして用いて、インデックス124から1グラムのビットマップを1つ選択する。
また、伸長部132は、今回のビットマップIDとスタック123に記憶された1つ前のビットマップIDとを結合したビット列を、2グラムの領域の先頭からのオフセットとして用いて、インデックス124から2グラムのビットマップを1つ選択する。また、伸長部132は、今回のビットマップIDとスタック123に記憶された1つ前のビットマップIDと2つ前のビットマップIDとを結合したビット列を、3グラムの領域の先頭からのオフセットとして用いて、インデックス124から3グラムのビットマップを1つ選択する。伸長部132は、選択した1グラム・2グラム・3グラムのビットマップに含まれる、現在伸長中のブロックに対応するビットを“1”に設定する。
(ステップS22)伸長部132は、スタック123に記憶された1つ前のビットマップIDと2つ前のビットマップIDを更新する。すなわち、伸長部132は、1つ前のビットマップIDを2つ前のビットマップIDに変更し、ステップS21で選択した今回のビットマップIDを1つ前のビットマップIDとしてスタック123に格納する。
(ステップS23)伸長部132は、ステップS21で選択したビットマップIDに対応する記号が、ブロックの末尾に相当するか(例えば、バッファ121における当該記号のアドレスが8kバイトの境界を示すか)判断する。記号がブロックの末尾である場合は処理をステップS24に進め、それ以外の場合は処理をステップS25に進める。
(ステップS24)伸長部132は、インデックス124に含まれる各ビットマップ内の更新対象となるビットの位置を示すブロック番号をインクリメントする。現在のブロック番号は、例えば、伸長部132がRAM102上に確保した記憶領域に記憶しておく。
(ステップS25)伸長部132は、ステップS21において、ステップS13またはステップS18で取得した1またはそれ以上のビットマップIDの全てを選択したか(末尾の記号に対応するビットマップIDまで選択したか)判断する。全て選択した場合は処理をステップS26に進め、未選択のものがある場合は処理をステップS21に進める。
(ステップS26)伸長部132は、ステップS14またはステップS18でバッファ121に追加した記号の数だけ、スライド窓の位置を後方にシフトさせる。
(ステップS27)伸長部132は、符号語部に続きの符号語があるか判断する。続きの符号語がある場合は処理をステップS12に進め、無い場合は処理を終了する。
図12は、構造体生成の第1の手順例を示すフローチャートである。図12に示す構造体生成処理は、前述のステップS11の中で実行される。
(ステップS31)ハフマン木生成部133は、記号0x00〜0xFFそれぞれの符号長から、前述のように二分ハフマン木を生成する。すなわち、ハフマン木生成部133は、符号化したときの符号長の小さい順に256通りの記号を並び替え、符号長が同じになる記号間では数値が小さい順に並び替える。また、ハフマン木生成部133は、符号長から各記号の出現頻度を推定する。そして、ハフマン木生成部133は、記号に対応する葉ノードを生成し、出現頻度に基づいて、葉ノードからルートノードに向かって枝を形成していく。ハフマン木生成部133は、生成した二分ハフマン木の枝を、ルートノードから葉ノードに向かって辿ることで、各記号に対応するハフマン符号を判定する。
(ステップS32)ハフマン木生成部133は、ステップS31で生成した二分ハフマン木に現れるルートノードおよび中間ノードの数をカウントする。そして、ハフマン木生成部133は、ハフマン木記憶部134に、カウントしたノード数に比例する大きさ(例えば、ノード数×2行×2バイト)の枝・葉領域を確保し、各ノードに記憶領域を割り当てる。なお、ルートノードには、枝・葉領域の先頭部分を割り当てるようにする。
(ステップS33)ハフマン木生成部133は、ステップS31で生成した二分ハフマン木に現れるルートノードおよび中間ノードの中から、1つノードを選択する。そして、ハフマン木生成部133は、選択したノードの左子ノードが葉ノードであるか判断する。左子ノードが葉ノードの場合は、処理をステップS34に進める。左子ノードが葉ノードでない(中間ノードである)場合は、処理をステップS35に進める。
(ステップS34)ハフマン木生成部133は、葉ノードに対応する伸長記号と、当該伸長記号に対応する1グラムのビットマップのビットマップIDとを含む葉データを生成する。ハフマン木生成部133は、生成した葉データを、ステップS33で選択したノードに割り当てられている記憶領域の前半(左子ノードに対応する行)に格納する。
(ステップS35)ハフマン木生成部133は、左子ノードとしての中間ノードに割り当てられている記憶領域の先頭を示すアドレスを含むポインタを生成する。ハフマン木生成部133は、生成したポインタを、ステップS33で選択したノードに割り当てられている記憶領域の前半(左子ノードに対応する行)に格納する。
(ステップS36)ハフマン木生成部133は、ステップS33で選択したノードの右子ノードが葉ノードであるか判断する。右子ノードが葉ノードの場合は、処理をステップS37に進める。右子ノードが葉ノードでない場合は、処理をステップS38に進める。
(ステップS37)ハフマン木生成部133は、葉ノードに対応する伸長記号と、当該伸長記号に対応する1グラムのビットマップのビットマップIDとを含む葉データを生成する。ハフマン木生成部133は、生成した葉データを、ステップS33で選択したノードに割り当てられている記憶領域の後半(右子ノードに対応する行)に格納する。
(ステップS38)ハフマン木生成部133は、右子ノードとしての中間ノードに割り当てられている記憶領域の先頭を示すアドレスを含むポインタを生成する。ハフマン木生成部133は、生成したポインタを、ステップS33で選択したノードに割り当てられている記憶領域の後半(右子ノードに対応する行)に格納する。
(ステップS39)ハフマン木生成部133は、ステップS33において、二分ハフマン木に現れるルートノードおよび中間ノードの全てを選択したか判断する。全て選択した場合は処理を終了し、未選択のノードがある場合は処理をステップS33に進める。
図13は、ハフマン復号の第1の手順例を示すフローチャートである。図13に示すハフマン復号処理は、前述のステップS13,S15,S16の中で実行される。
(ステップS41)伸長部132は、ハフマン木記憶部134に記憶された構造体データのヘッダ領域を参照して、枝・葉領域の先頭アドレスを確認する。そして、伸長部132は、構造体データ内の現在参照している位置を、枝・葉領域の先頭に設定する。
(ステップS42)伸長部132は、圧縮ファイル111に含まれる符号語部のビット列から、伸長が完了していない部分(未抽出の部分)の先頭1ビットを抽出する。
(ステップS43)伸長部132は、ステップS42で抽出した1ビットの値を、構造体データ内の現在参照している位置からの相対アドレス(オフセット)として用いて、1行分のデータ(葉データまたはポインタ)を選択する。すなわち、伸長部132は、抽出したビットが“0”のときは左子ノードに対応するデータを選択して、抽出したビットが“1”のときは右子ノードに対応するデータを選択する。
(ステップS44)伸長部132は、ステップS43で選択したデータの先頭ビットを確認する。先頭ビット=0である場合、選択したデータはポインタであると判断し、処理をステップS45に進める。先頭ビット=1である場合、選択したデータは葉データであると判断し、処理をステップS46に進める。
(ステップS45)伸長部132は、ステップS43で選択したデータであるポインタからアドレスを抽出し、構造体データ内のアドレスが差し示す位置にジャンプする(現在参照している位置を更新する)。そして、処理をステップS42に進める。
(ステップS46)伸長部132は、ステップS43で選択したデータである葉データから、伸長記号とビットマップIDを抽出する。ただし、前述のステップS15,S16では、葉データに含まれるビットマップIDは使用されない。伸長部132は、ステップS15,S16では、葉データからビットマップIDを抽出しなくてもよい。
図14は、第1のインデックス生成例を示す図である。図14は、先頭ビット=0である符号語を伸長したときの動作を示している。伸長部132は、符号語の先頭ビットに続くビット列を用いて、ハフマン木の構造体データから葉データを検索し、葉データから伸長記号とビットマップIDを抽出する。伸長部132は、抽出した伸長記号をバッファ121に格納し、抽出したビットマップIDをバッファ122に格納する。
また、伸長部132は、葉データから抽出したビットマップIDを識別子として、インデックス124の中から1グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、葉データから抽出したビットマップIDとスタック123に記憶された1つ前のビットマップIDを結合した値を識別子として、インデックス124の中から2グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、葉データから抽出したビットマップIDとスタック123に記憶された1つ前および2つ前のビットマップIDを結合した値を識別子として、インデックス124の中から3グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。
また、伸長部132は、スタック123に記憶されていた1つ前のビットマップIDを、2つ前のビットマップIDに変更する(例えば、2つ前のビットマップIDとしてスタック123に格納し直す)。また、伸長部132は、葉データから抽出したビットマップIDを、1つ前のビットマップIDとしてスタック123に格納する。
図15は、第2のインデックス生成例を示す図である。図15は、先頭ビット=1である符号語を伸長したときの動作を示している。伸長部132は、符号語の先頭ビットに続くビット列から、ハフマン木の構造体データを参照して「先頭アドレス」と「バイト数」を復元する。そして、伸長部132は、スライド窓内の「先頭アドレス」と「バイト数」によって特定される範囲にある記号列を、バッファ121の末尾に複製し、複製した記号列に対応するビットマップIDの列をバッファ122の末尾に複製する。
また、伸長部132は、複製した1番目のビットマップIDを識別子として、インデックス124の中から1グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、複製した1番目のビットマップIDとスタック123に記憶された1つ前のビットマップIDを結合した値を識別子として、インデックス124の中から2グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、複製した1番目のビットマップIDとスタック123に記憶された1つ前および2つ前のビットマップIDを結合した値を識別子として、インデックス124の中から3グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。
また、伸長部132は、スタック123に記憶されていた1つ前のビットマップIDを、2つ前のビットマップIDに変更する。また、伸長部132は、複製した1番目のビットマップIDを、1つ前のビットマップIDとしてスタック123に格納する。伸長部132は、以上に説明したスタック123およびインデックス124の更新を、複製した2番目以降のビットマップIDそれぞれについても実行する。
以上の第2の実施の形態の説明では、ハフマン木の構造体データに、伸長記号とは別にビットマップIDを格納しておき、このビットマップIDを用いてインデックス124の中から伸長記号に対応するビットマップを選択することとした。ただし、伸長記号としての数値がビットマップIDを兼ねる場合もある。例えば、インデックス124が、256個の1グラムのビットマップを含み、これら256個のビットマップが、伸長記号としての数値0x00〜0xFFの順に並んでいる場合が考えられる。その場合、ハフマン木の構造体データに、伸長記号と別にビットマップIDを格納しなくてもよい。また、その場合、バッファ部120にバッファ122を設けなくてもよい。
図16は、第3のインデックス生成例を示す図である。図16は、先頭ビット=0である符号語を伸長したときの動作を示している。伸長部132は、符号語の先頭ビットに続くビット列を用いて、ハフマン木の構造体データから葉データを検索し、葉データから伸長記号を抽出する。伸長部132は、抽出した伸長記号をバッファ121に格納する。
伸長部132は、ビットマップIDを兼ねる伸長記号を識別子として、インデックス124の中から1グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、伸長記号とスタック123に記憶された1つ前のビットマップIDを結合した値を識別子として、インデックス124の中から2グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、伸長記号とスタック123に記憶された1つ前および2つ前のビットマップIDを結合した値を識別子として、インデックス124の中から3グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。
また、伸長部132は、スタック123に記憶されていた1つ前のビットマップIDを、2つ前のビットマップIDに変更する。また、伸長部132は、ビットマップIDを兼ねる伸長記号を、1つ前のビットマップIDとしてスタック123に格納する。
図17は、第4のインデックス生成例を示す図である。図17は、先頭ビット=1である符号語を伸長したときの動作を示している。伸長部132は、符号語の先頭ビットに続くビット列から、ハフマン木の構造体データを参照して「先頭アドレス」と「バイト数」を復元する。そして、伸長部132は、スライド窓内の「先頭アドレス」と「バイト数」によって特定される範囲にある記号列を、バッファ121の末尾に複製する。
また、伸長部132は、ビットマップIDを兼ねる複製した記号の列のうち1番目の記号を識別子として、インデックス124の中から1グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、1番目の記号とスタック123に記憶された1つ前のビットマップIDを結合した値を識別子として、インデックス124の中から2グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。また、伸長部132は、1番目の記号とスタック123に記憶された1つ前および2つ前のビットマップIDを結合した値を識別子として、インデックス124の中から3グラムのビットマップを選択し、選択したビットマップ内の1つのビットを“1”に設定する。
また、伸長部132は、スタック123に記憶されていた1つ前のビットマップIDを、2つ前のビットマップIDに変更する。また、伸長部132は、ビットマップIDを兼ねる1番目の記号を、1つ前のビットマップIDとしてスタック123に格納する。伸長部132は、以上に説明したスタック123およびインデックス124の更新を、ビットマップIDを兼ねる複製した2番目以降の記号それぞれについても実行する。
なお、以上の第2の実施の形態の説明では、インデックス124における「1グラム」を、文字コード非依存の1バイト記号(0x00〜0xFF)とした。ただし、「1グラム」を、文字コード依存の1文字としてもよい。例えば、1文字が2バイトで表される文字コード体系の場合、「1グラム」は2バイトの文字に相当し、「2グラム」は4バイトで表される文字列に相当し、「3グラム」は6バイトで表される文字列に相当する。インデックス124では、1文字当たりのバイト数が異なる複数の文字(例えば、1バイト文字と2バイト文字)が「1グラム」として混在していてもよい。
第2の実施の形態の情報端末装置100によれば、伸長記号に対応するビットマップIDがハフマン木の構造体データに登録されているため、圧縮ファイル111の伸長と並行して、伸長データに対応するインデックス124を効率的に生成できる。すなわち、構造体データに登録されたビットマップIDを用いて、インデックス124内の所望のビットマップが記憶されている領域に直接アクセスすることで、RAM102へのアクセスを減らすことができる。また、1つ前および2つ前のビットマップIDを記憶するスタック123を設けることで、バッファ122から1つ前および2つ前のビットマップIDを検索するよりも、効率的に2グラム・3グラムのビットマップにアクセスできる。また、圧縮ファイル111の伸長が完了した時点で、伸長データに対応するインデックス124が生成されているため、伸長データに対する検索をすぐに開始することが可能となる。
[第3の実施の形態]
第3の実施の形態を説明する。前述の第2の実施の形態との差異を中心に説明し、第2の実施の形態と同様の事項は説明を省略する。第3の実施の形態は、ハフマン木の構造体データの構造と構造体データを用いてハフマン符号を復号する方法が、第2の実施の形態と異なる。第3の実施の形態の情報端末装置は、第2の実施の形態の情報端末装置100と同様に、図2に示したようなハードウェア構成によって実現でき、また、図8に示したようなソフトウェア構成によって実現できる。以下では、第2の実施の形態で用いた図2,8の中の符号を用いて、第3の実施の形態を説明することとする。
図18は、変形したハフマン木の例を示す図である。第3の実施の形態の情報端末装置は、ハフマン木を表した構造体データを参照して圧縮ファイル111を伸長するにあたり、伸長処理の効率を向上させるためにハフマン木を変形しておく。
情報端末装置は、ハフマン木によって決定される256個の符号の最大符号長を特定し、最大符号長を上位nビットと下位mビット(n,mは1以上の整数)に分ける。閾値である“n”は、固定の所定値であってもよいし、符号長がnビット未満である記号の出現頻度の合計が所望の頻度になるように符号長の情報から決定してもよい。そして、情報端末装置は、1つの枝に1ビットを対応付けた二分ハフマン木を、1つの枝に複数ビットを対応付けることができ葉ノードの深さが1または2であるハフマン木に変形する。変形されたハフマン木では、1つの記号が複数の葉ノードに対応付けられ得る。
すなわち、情報端末装置は、nビット未満の符号の末尾に冗長なビットを付加することで、nビット以下の符号の長さをnビットに揃える。例えば、n=4の場合、符号0が8個のビット列0000〜0111に変換され、符号10が4個のビット列1000〜1011に変換される。また、情報端末装置は、nビットを超える符号から上位nビットのビット列を分離し、残りのビット列の長さをmビットに揃える。例えば、n=4,m=2の場合、符号11110がビット列1111と下位のビット列00,01に変換され、符号111110がビット列1111と下位のビット列10に変換される。
変形されたハフマン木では、上位nビットのビット列を用いて、ルートノードから符号長がnビット以下の記号に対応する葉ノードを辿ることができる。また、上位nビットのビット列を用いて中間ノードを辿り、下位mビットのビット列を用いて、中間ノードから符号長がnビットを超える記号に対応する葉ノードを辿ることができる。すなわち、変形されたハフマン木では、出現頻度が高い記号は枝を1回辿ることで符号から検索でき、出現頻度が低い記号は枝を2回辿ることで符号から検索することができる。
変形されたハフマン木を用いて圧縮ファイル111を伸長する場合、情報端末装置は、圧縮ファイル111からn+mビットのビット列を1回に抽出し、上位nビット、または、上位nビットと下位mビットの組み合わせから、伸長記号を取得する。このとき、抽出したn+mビットの全体が、伸長記号に対応する符号を構成するわけではない。図18のハフマン木において、例えば、圧縮ファイル111からビット列000110が抽出されたときは、記号0x00が伸長記号として取得される。ただし、記号0x00は1ビットの符号0に符号化されていることから、抽出した残りの5ビットのビット列00110は次の符号や符号語を構成する可能性があり、復号済とは扱わないことになる。
図19は、ハフマン木を表した構造体データの第2の例を示す図である。図19に示すような構造体データが、ハフマン木生成部133によって生成されてハフマン木記憶部134に格納される。図19に記載した「1行」は、2バイトの記憶領域に相当する。ハフマン木の構造体は、ヘッダ領域、上位枝領域、下位枝領域および葉領域を含む。
ヘッダ領域には、構造体データのサイズや領域間の境界を示すアドレスなど、管理用の情報が格納される。上位枝領域には、それぞれが2バイトで表された2のn乗個のポインタが格納される。上位枝領域の各ポインタは、下位枝領域にある何れかのポインタ集合の先頭アドレスまたは葉領域にある何れかの葉データの先頭アドレスを含む。上位枝領域のポインタの先頭ビットは、ポインタであることを表すため“0”に設定される。上位枝領域から葉領域へのポインタは、図18のルートノードから葉ノードへの枝に相当し、複数の上位枝領域のポインタが同一の葉データを指し示すことがある。上位枝領域から下位枝領域へのポインタは、図18のルートノードから中間ノードへの枝に相当する。
下位枝領域には、それぞれが2バイトで表された2のm乗個のポインタがaセット(aは1以上の整数)格納される。下位枝領域の各ポインタは、葉領域にある何れかの葉データの先頭アドレスを含む。下位枝領域のポインタの先頭ビットは、ポインタであることを表すため“0”に設定される。下位枝領域から葉領域へのポインタは、図18の中間ノードから葉ノードへの枝に相当し、複数の下位枝領域のポインタが同一の葉データを指し示すことがある。集合数aは、変形したハフマン木における中間ノードの数に相当する。
葉領域には、256個の記号0x00〜0xFFに対応する葉データが格納される。葉領域では、図7,18の葉ノードと同様の順序に葉データが整列されている。すなわち、符号長の小さい記号に対応する葉データほどアドレスの小さい位置に格納され、また、符号長の同じ記号の中では数値の小さい記号に対応する葉データほどアドレスの小さい位置に格納される。各記号の葉データは、伸長記号、その記号を符号化したときのハフマン符号、符号長の情報およびビットマップIDを含む。葉データの先頭ビットは、葉データであることを表すため“1”に設定される。葉データは、例えば、6バイトで表される。ただし、葉データのサイズは、構造体データを生成する時点で所定値に決めておけばよく、葉データにどの様な情報を含めるかに応じて調整できる。例えば、葉データにハフマン符号を含めなくてもよく、その場合は4バイトで表現できる。
前述のようにn+mビットのビット列が抽出されると、上位nビットのビット列が、上位枝領域の先頭を基準とした相対アドレス(オフセット)として用いられて、オフセットに応じた位置に格納されている上位枝領域のポインタが選択される。選択したポインタが葉データを指し示していないとき、下位mビットのビット列が、上位枝領域のポインタが指し示す位置からのオフセットとして用いられて、オフセットに応じた位置に格納されている下位枝領域のポインタが選択される。このように、上位枝領域からポインタを1回または2回辿ることで、葉領域にある葉データを参照することができる。
図20は、構造体生成の第2の手順例を示すフローチャートである。図20に示す構造体生成処理は、第2の実施の形態で述べたステップS11の中で実行される。
(ステップS51)ハフマン木生成部133は、記号0x00〜0xFFそれぞれの符号長から、前述のように二分ハフマン木を生成する。ハフマン木生成部133は、生成した二分ハフマン木の枝を辿ることで、各記号に対応するハフマン符号を判定する。
(ステップS52)ハフマン木生成部133は、ハフマン木記憶部134に、6バイト(または、所定バイト)×256の大きさの葉領域を確保する。
(ステップS53)ハフマン木生成部133は、ステップS52で確保した葉領域に、ステップS51で並べた記号順に各記号に対応する葉データを書き込む。各記号の葉データは、伸長記号とハフマン符号と符号長を示す情報とビットマップIDを含む。
(ステップS54)ハフマン木生成部133は、記号0x00〜0xFFに対応する符号の最長符号長を、前述のように上位nビットと下位mビットに分割する。
(ステップS55)ハフマン木生成部133は、ハフマン木記憶部134に、2バイト×2nの上位枝領域を確保する。また、ハフマン木生成部133は、2n通りのnビットのビット列のうち、ビット数がnを超える符号のプレフィックスになっているものの数a(変形したハフマン木の中間ノードの数)を算出する。そして、ハフマン木生成部133は、ハフマン木記憶部134に、2バイト×a×2mの下位枝領域を確保する。
(ステップS56)ハフマン木生成部133は、葉領域にある1つの記号分の葉データを、アドレスの小さい方から選択する。そして、ハフマン木生成部133は、選択した葉データの示す符号長が閾値nより大きいか判断する。符号長がnより大きい場合は処理をステップS58に進め、符号長がn以下の場合は処理をステップS57に進める。
(ステップS57)ハフマン木生成部133は、符号長をLとして、上位枝領域のポインタ数=2のn−L乗を算出する。そして、ハフマン木生成部133は、上位枝領域の中でポインタをまだ書き込んでいない領域のうちアドレスの小さい方から順に、算出したポインタ数だけ、ステップS56で選択した葉データの先頭アドレスを含むポインタを書き込む。例えば、n=11の場合、上位枝領域には、1ビットの符号に対応する葉データを指すポインタは1024個書き込まれ、2ビットの符号に対応する葉データを指すポインタは512個書き込まれ、10ビットの符号に対応する葉データを指すポインタは2個書き込まれ、11ビットの符号に対応する葉データを指すポインタは1個書き込まれる。
(ステップS58)ハフマン木生成部133は、下位枝領域の中でポインタをまだ書き込んでいない領域の先頭アドレスを確認する。そして、ハフマン木生成部133は、上位枝領域の中の、選択した葉データが示すハフマン符号の上位nビットによって特定される位置に、確認した下位枝領域のアドレスを含むポインタを書き込む。ただし、上位nビットによって特定される位置にポインタを書き込み済のときは、書き込まなくてよい。
(ステップS59)ハフマン木生成部133は、下位枝領域のポインタ数=2のn+m−L乗を算出する。そして、ハフマン木生成部133は、下位枝領域の中でポインタをまだ書き込んでいない領域のうちアドレスの小さい方から順に、算出したポインタ数だけ、選択した葉データの先頭アドレスを含むポインタを書き込む。例えば、n=11,m=3の場合、下位枝領域には、12ビットの符号に対応する葉データを指すポインタは4個書き込まれ、14ビットの符号に対応する葉データを指すポインタは1個書き込まれる。
(ステップS60)ハフマン木生成部133は、ステップS56で全ての記号に対応する葉データを選択したか判断する。全ての葉データを選択した場合は処理を終了し、未選択の葉データがある場合は処理をステップS56に進める。
図21は、ハフマン復号の第2の手順例を示すフローチャートである。図21に示すハフマン復号処理は、前述のステップS13,S15,S16の中で実行される。
(ステップS61)伸長部132は、圧縮ファイル111に含まれる符号語部の符号語列から、伸長が完了していないn+mビットのビット列を抽出する。
(ステップS62)伸長部132は、ハフマン木記憶部134に記憶された構造体データのヘッダ領域を参照して、上位枝領域の先頭アドレスを確認する。そして、伸長部132は、ステップS61で抽出したビット列の上位nビットを、上位枝領域の先頭からの相対アドレス(オフセット)として用いて、上位枝領域にあるポインタを1つ選択する。伸長部132は、選択したポインタが指し示す位置(ポインタに含まれるアドレスによって特定される位置)に記憶されているデータを取得する。
(ステップS63)伸長部132は、ステップS62で取得したデータの先頭ビットを確認する。先頭ビット=1の場合、取得したデータは葉データであると判断し、処理をステップS65に進める。先頭ビット=0の場合、取得したデータは下位枝領域のポインタであると判断し、処理をステップS64に進める。
(ステップS64)伸長部132は、ステップS61で抽出したビット列の下位mビットを、上位枝領域のポインタが指し示す位置からのオフセットとして用いて、下位枝領域にあるポインタを1つ選択する。そして、伸長部132は、選択したポインタが指し示す位置(ポインタに含まれるアドレスによって特定される位置)の葉データを取得する。
(ステップS65)伸長部132は、ステップS62またはステップS64で取得した葉データから、伸長記号とビットマップIDを抽出する。伸長部132は、葉データからビットマップIDを抽出する。ただし、前述のステップS15,S16では、葉データに含まれるビットマップIDは使用されない。伸長部132は、ステップS15,S16では、葉データからビットマップIDを抽出しなくてもよい。
(ステップS66)伸長部132は、ステップS62またはステップS64で取得した葉データから符号長の情報を抽出し、符号語列のどの位置まで伸長が完了したかを示すカウンタを符号長だけ進める。カウンタはRAM102に記憶されている。
図22は、ハフマン復号におけるビット演算の例を示す図である。ここでは、圧縮ファイル111に用いられている符号の最長符号長が14であり、n=11であるとする。
情報端末装置は、バッファに格納した符号語列のうち伸長が完了していない部分の先頭位置を管理するため、RAM102上にバイトカウンタとビットカウンタを保持する。バイトカウンタは、伸長が完了していない部分の先頭が、バッファの先頭から何バイト目に属するかを示している。ビットカウンタは、伸長が完了していない部分の先頭が、バイトの切れ目(8ビット毎の切れ目)から何ビット目にあるかを示している。ビットカウンタは0〜7の範囲の値を取り、一巡するとバイトカウンタがインクリメントされる。
伸長部132は、バッファに格納された符号語列から、まず4バイト(32ビット)単位でビット列を切り出す。すなわち、伸長部132は、バイトカウンタが示す位置を先頭とする32ビットのビット列を、long型変数に代入する。このとき、long型変数の先頭ビットはバイトの切れ目であり、伸長が完了していない部分の先頭とは限らない。
次に、伸長部132は、long型変数のビット列に8通りのマスクパターンの何れかを適用することで、伸長が完了していない14ビットのビット列を抽出する。マスクパターンは、32ビットのうち連続する14ビットが“1”で他のビットが“0”に設定されたビット列であり、RAM102上に記憶されている。マスクパターンには、MSBから数えて1〜14ビット目が“1”であるもの、2〜15ビット目が“1”であるもの、3〜16ビット目が“1”であるもの、4〜17ビット目が“1”であるもの、5〜18ビット目が“1”であるもの、6〜19ビット目が“1”であるもの、7〜20ビット目が“1”であるもの、8〜21ビット目が“1”であるものが存在する。伸長部132は、ビットカウンタに応じて何れか1つのマスクパターンを選択し、long型変数のビット列と選択したマスクパターンの間でビット毎の論理積を行う。そして、伸長部132は、論理積の結果をシフトして14ビットのビット列を取得する。
次に、伸長部132は、14ビットのビット列のうち上位11ビットを、構造体データの上位枝領域からポインタを1つ選択するためのオフセットとして使用する。また、伸長部132は、14ビットのビット列のうち下位3ビットを、構造体データの下位枝領域からポインタを1つ選択するためのオフセットとして使用する。これにより、伸長部132は、葉領域から伸長記号とビットマップIDと符号長を示す情報とを取得する。ビットマップIDは、インデックス124の更新のために用いられる。そして、伸長部132は、符号長だけビットカウンタの値を増加させる。ビットカウンタが一巡した(ビットカウンタが7から0に戻った)ときは、一巡する毎にバイトカウンタをインクリメントする。
第3の実施の形態の情報端末装置によれば、第2の実施の形態と同様の効果が得られる。また、第3の実施の形態では、ビット数がn以下の符号については構造体データのポインタを1回辿れば伸長記号とビットマップIDを検索でき、ビット数がnを超える符号についてはポインタを2回辿れば伸長記号とビットマップIDを検索できる。よって、符号語の1ビット毎に、二分ハフマン木の通りにポインタを辿る方法と比べて、RAM102へのアクセス回数を削減でき、圧縮ファイル111の伸長を効率化できる。
また、ビット数がnを超える符号に対応する記号を2段階のポインタで辿るようにすることで、全ての記号を1段階のポインタで辿る方法と比べて、同じ伸長記号を指し示す冗長なポインタの数を削減でき、構造体データのデータ量を抑制できる。例えば、最大符号長が14である場合、全ての記号を1段階のポインタで辿れるようにすると、214=16k(65536)個のポインタが生成される。これに対し、第3の実施の形態の方法では、n=11とすると、上位枝領域に211=2k(2048)個のポインタが生成され、下位枝領域に8個のポインタが複数セット生成される。
なお、第3の実施の形態においても、第2の実施の形態で述べたように、伸長記号としての数値がビットマップIDを兼ねる場合がある。その場合、ハフマン木の構造体データに、伸長記号と別にビットマップIDを格納しなくてもよい。また、その場合、バッファ部120にバッファ122を設けなくてもよい。
[第4の実施の形態]
第4の実施の形態を説明する。前述の第2の実施の形態との差異を中心に説明し、第2の実施の形態と同様の事項は説明を省略する。第4の実施の形態は、2つのブロックに跨がる単語を両方のブロックに属しているものとして扱って、インデックスを生成する。これにより、ユーザから指定されたキーワードが2つのブロックに跨がるときに、2つのブロックの何れも検索結果に含まれないことを避けることができる。第4の実施の形態の情報端末装置は、第2の実施の形態の情報端末装置100と同様に、図2に示したようなハードウェア構成によって実現でき、また、図8に示したようなソフトウェア構成によって実現できる。以下では、図2,8の中の符号を用いて、第4の実施の形態を説明する。
図23は、ファイル伸長の第2の手順例を示すフローチャートである。図23のフローチャートの処理は、図11のフローチャートが示す第2の実施の形態の処理に代えて、図10のフローチャートの処理に続けて実行される。
(ステップS71)伸長部132は、ステップS13またはステップS18で取得した1またはそれ以上のビットマップIDから、先頭に近い順に1つビットマップIDを選択する。伸長部132は、選択したビットマップIDと、スタック123に記憶された1つ前のビットマップIDと、スタック123に記憶された2つ前のビットマップIDとに基づいて、インデックス124から1グラム・2グラム・3グラムのビットマップを選択する。伸長部132は、選択した1グラム・2グラム・3グラムのビットマップに含まれる現在伸長中のブロックに対応するビットを“1”に設定する。
(ステップS72)伸長部132は、スタック123に記憶されていた1つ前のビットマップIDを2つ前のビットマップIDに変更し、ステップS71で選択した今回のビットマップIDを、1つ前のビットマップIDとしてスタック123に格納する。
(ステップS73)伸長部132は、ステップS71で選択したビットマップIDに対応する記号が、単語などの所定単位の先頭であるか判断する。例えば、伸長した記号列が英文である場合は、直前のスペース(空白)を検出することで、その記号が単語の先頭であると判断する。また、伸長した記号列が日本語文である場合は、直前の句読点を検出することで、その記号が文や句の先頭であると判断する。記号が所定単位の先頭である場合は処理をステップS74に進め、それ以外の場合は処理をステップS75に進める。
(ステップS74)伸長部132は、バッファ121における、ステップS71で選択したビットマップIDに対応する記号の位置を示すアドレスを保存しておく。
(ステップS75)伸長部132は、ステップS71で選択したビットマップIDに対応する記号の直前が、単語などの所定単位の末尾であるか判断する。例えば、伸長した記号列が英文の場合は、スペースを検出することで、直前の記号が単語の末尾であると判断する。また、伸長した記号列が日本語文の場合は、句読点を検出することで、直前の記号が文や句の末尾であると判断する。直前の記号が所定単位の末尾である場合は処理をステップS76に進め、それ以外の場合は処理をステップS77に進める。
(ステップS76)伸長部132は、単語などの所定単位の記号列がブロックを跨いでいるか、すなわち、ステップS74で保存したアドレスとステップS75で検出した末尾のアドレスとの間に、ブロックの境界が存在するか判断する。ブロックを跨いでいる場合は処理をステップS80に進め、それ以外の場合は処理をステップS77に進める。
(ステップS77)伸長部132は、ステップS71において、ステップS13またはステップS18で取得した1またはそれ以上のビットマップIDの全てを選択したか(取得したビットマップIDの列の末尾まで選択したか)判断する。全て選択した場合は処理をステップS78に進め、未選択のものがある場合は処理をステップS71に進める。
(ステップS78)伸長部132は、ステップS14またはステップS18でバッファ121に追加した記号の数だけ、スライド窓の位置を後方にシフトさせる。
(ステップS79)伸長部132は、符号語部に続きの符号語があるか判断する。続きの符号語がある場合は処理をステップS12に進め、無い場合は処理を終了する。
(ステップS80)伸長部132は、バッファ121から、ステップS74で保存したアドレス以降にある記号列(例えば、最後の単語)を削除する。また、バッファ122から、削除した記号列に対応するビットマップIDの列を削除する。
(ステップS81)伸長部132は、ステップS80で行った記号列およびビットマップIDの削除に合わせて、スライド窓とスタックの状態を、削除した記号列を伸長する前の状態に戻す。すなわち、伸長部132は、バッファ121から削除した記号の数だけスライド窓を前方にシフトさせる。また、伸長部132は、ステップS80の削除を行った後のバッファ122の末尾に格納されている2つのビットマップIDを、1つ前および2つ前のビットマップIDとしてスタック123に格納する。
(ステップS82)伸長部132は、インデックス124に含まれる各ビットマップ内の更新対象となるビットの位置を示すブロック番号をインクリメントする。
(ステップS83)伸長部132は、ステップS80で削除した記号列に対応する符号語を、伸長が完了していないものとみなして、処理をステップS12に進める。このように、伸長部132は、2つのブロックに跨がる所定単位(例えば、単語)の記号列については、伸長を2回行うことで、両方のブロックに属するものとして扱う。伸長部132は、その記号列全体が前のブロックに属するとしてインデックス124を更新し、その後、その記号列全体が後のブロックにも属するとしてインデックス124を更新する。
図24は、ブロック境界におけるインデックス生成例を示す図である。図24に示す例では、英単語“about”を構成する5文字のうち、前半2文字がブロック#2に含まれ、後半3文字がブロック#3に含まれている場合を考える。
前半2文字“ab”が伸長されると、インデックス124では、1グラム“a”や2グラム“ab”に対応するビットマップ内のブロック#2に対応するビットが“1”に設定される。続けて、後半3文字“out”が伸長されると、ブロックがまだ切り替わっていないとみなされ、インデックス124では、1グラム“o”や2グラム“bo”や3グラム“abo”に対応するビットマップ内のブロック#2に対応するビットが“1”に設定される。この時点では、ブロック#3に対応するビットは更新されない。
英単語“about”の1回目の伸長が完了すると、その英単語がバッファ121から削除され、ブロックがブロック#2からブロック#3に切り替わったとみなされる。そして、前半2文字“ab”が再び伸長されると、インデックス124では、1グラム“a”や2グラム“ab”に対応するビットマップ内のブロック#3に対応するビットが“1”に設定される。続けて、後半3文字“out”が再び伸長されると、インデックス124では、1グラム“o”や2グラム“bo”や3グラム“abo”に対応するビットマップ内のブロック#3に対応するビットが“1”に設定される。
このように、ブロック#2,#3に跨がる英単語“about”がブロック#2,#3の両方に属するとみなされて、インデックス124が生成される。これにより、ユーザが“about”をキーワードとして指定したときに、ブロック#2,#3を検索できる。なお、図23,24に示した2つのブロックに跨がる記号列を2回伸長する方法は、その記号列が両方のブロックに属するとみなしてインデックス124を生成するための方法の一例であり、他の方法でインデックス124を生成することもできる。また、2つのブロックに跨がる記号列を、2つのブロックの何れか一方のみに属するとみなしてもよい。
第4の実施の形態の情報端末装置によれば、第2の実施の形態と同様の効果が得られる。また、第4の実施の形態では、ユーザから指定されたキーワードが2つのブロックに跨がっていても、そのキーワードが現れる箇所を特定でき、検出漏れを抑制できる。
なお、前述のように、第1の実施の形態の情報処理は、情報処理装置10にプログラムを実行させることで実現できる。また、第2〜第4の実施の形態の情報処理は、情報端末装置100にプログラムを実行させることで実現できる。プログラムは、コンピュータ読み取り可能な記録媒体(例えば、記録媒体21)に記録しておくことができる。記録媒体としては、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、FDおよびHDDが含まれる。光ディスクには、CD、CD−R(Recordable)/RW(Rewritable)、DVDおよびDVD−R/RWが含まれる。
プログラムを流通させる場合、例えば、当該プログラムを記録した可搬記録媒体が提供される。また、プログラムを他のコンピュータの記憶装置に格納しておき、ネットワーク経由でプログラムを配布することもできる。コンピュータは、例えば、可搬記録媒体に記録されたプログラムまたは他のコンピュータから受信したプログラムを、記憶装置(例えば、不揮発性メモリ103)に格納し、当該記憶装置からプログラムを読み込んで実行する。ただし、可搬記録媒体から読み込んだプログラムを直接実行してもよく、他のコンピュータからネットワークを介して受信したプログラムを直接実行してもよい。