アイデアの甕

アイデアを放り込んでおくと甕は腐臭を発しない

当サイトではアフィリエイトプログラムを利用して商品を紹介しています。

ローカルにダウンロードした日本語PDFをRubyとpopplerで読み込む際に出たエラーの解消法

たのしいRuby 第5版

 

 

Rubyで日本語PDFを読み込みましょう。

 

qiita.com

 

d.hatena.ne.jp

 

先達の知恵を拝借。そういえば「poppler-data」に関しての試行錯誤もあったので、機会があればまた書きます。→ 書きました。「Windows上のRubyで日本語PDFを読むためにpoppler-dataをインストールする方法」

 

で、上記「ねこのここねこ」さんが示すサンプルを打ち込み、無事コンソールに日本語PDFの内容が日本語で示されましたとさ。

 

めでたしめでたし…じゃないんですね、これが。

 

 

PDFをダウンロードしたら、読めなくなった。

サンプルで使用したPDFファイルをブラウザ(Chrome)でダウンロードして、ローカル環境(実行rbファイルと同一ディレクトリ)に置いて読み込んでみた。

 

require 'poppler'

slide = Poppler::Document.new(open("i2document2.pdf").read)
puts slide.first.get_text;

 

そしたら、出るわ出るわ。エラーのオン・パレード。

 

PDF document is damaged (GLib::Error)

Poppler-INFO **:Syntax error at position -1: Couldn't read xref table

Poppler-INFO **:Syntax error at position -1: Couldn't find trailer dictionary

 

今やってみると、このようなエラーが吐き出されます。

 

※どっかでInvalid XRef entryというエラーも見たのだけれど、今は再現できない…。

 

追記:

あー、テスト用のコードだとPoppler::Documentをeachメソッドであーだこーだするために.firstを使ってなかったわ!たぶんInvalid XRef entryはこっちのエラーでした。

 

解決策

で、何が起こっていたかというとKernel.#openがちゃんとopenできてなかったようで。

 

というか、上記リンク先のサンプルでは(httpなんで当然ですが)標準ライブラリの'open-uri'が利用されていて、問題を暗黙に解決していたようです。

 

そう、暗黙に。

 

こちらの話は『たのしいRuby 第5版』の397ページに記載されています。

 

また、open-uriライブラリなどを使い、ネットワーク越しにファイルを取得する場合、その文字コードが分からない場合があります。その場合にも、エンコーディングはASCII-8BITになります。

 

# encoding: utf-8
require 'open-uri'
str = open("http://www.example.jp/").read
p str.encoding  #=>  #<Encoding:ASCII-8BIT>

 

 で、さきほどのローカルでopenしてreadしたPDFファイルは、エンコードとしてUTF-8が指定されていたわけでして。

 

こちらはopen-uriライブラリを用いないネイティブopenになるので、明示的にエンコードを指定しなければならないようです。

 

ただ、今回の場合はASCII-8BITにはBINARYという別名があると『たのしいRuby』には記載がありまして、openのオプションに"rb"を指定してやると(デフォルトでは"r")。読み込み時に「バイナリの"b"!」をしてやるとエンコードがASCII-8BITになるようです。

 

slide = Poppler::Document.new(open("i2document2.pdf", "rb").read)

 

こうしてやると、ちゃんと読み込んで中身も日本語で表示することが出来ました。

 

そう、いつだって日本語読み書きの問題はエンコーディングに隠蔽されている…のかもしれない。

 

以下、試行錯誤の記録

PDFの構造なんてよく分かってないので、.pdfファイルをテキストエディタで開くことができるなんて、初めて知りました。

 

まぁそんな感じなので、行き当たりばったりというか、試行錯誤も暗中模索も日常茶飯で今思えばふふふ、となるようなところの壁に頭をぶっつけたのやなぁ(しみじみ)。

 

Google Chromeのせい?

 まず疑ったのは、ダウンロードしている輩(Chromeさん)が悪さ(ファイル改変)しているんじゃないかと。だって、同じファイルのはずなのに読み込めないとしたら、関わったのはChromeさんしかいない…はず(いつだって諸悪の根源の自分自身を除く)。

 

productforums.google.com

 

上記フォーラムで、似たような、関連ありそうな話題を発見。「やはりか」と思いFirefoxやIEで当のPDFをダウンロードするものの、状況は変わらず。

 

StringIO?、Tempfile?

挙動の違いはオブジェクトの違い!というわけで、openしたオブジェクトのクラスを調べてみる。

 

開いたファイルオブジェクトは StringIO もしくは Tempfile ですが OpenURI::Meta モジュールで拡張されていて、メタ情報を獲得する メソッドが使えます

library open-uri (Ruby 2.3.0)

 

 

あ、使ったことない奴や…。

 

と、いうわけで色々挙動を調べてみたりもしたのですが、解決に至らず。最終的には冒頭に示した方法で「バイナリファイルとして読み込む」ことでエラーは解消されました。

 

あまり大きな声では言えませんが…

 

open-uriライブラリの暗黙のエンコーディングやStringIOやTempfileなんかも、全部『たのしいRuby 第5版』に掲載されてますよ!

 

今一度、基礎固めしてみてはいかが?