PDFBoxで取得したテキストの空白置換
SlideShareがやっているように、PDFスライドから抽出したしたテキストから、改行やタブを半角スペース1つに置換を試みた際にはまったのでメモ。
取得したいのはSlideShareのページ下部に表示されているこの文字列。
1. PDFBoxでテキスト抽出
PDFTextStripper.getText(PDDocument doc) がIOExceptionを投げるため、IntStreamでループを回すとforEachブロック内での例外処理が強制される。シンプルにするためにfor文で書いてみる。
PDDocument doc = PDDocument.load("/Path/PDFSlide.pdf"); List<PDPage> pages = doc.getDocumentCatalog().getAllPages(); PDFTextStripper stripper = new PDFTextStripper(); for (int i = 1; i <= doc.getNumberOfPages(); i++) { stripper.setStartPage(i); stripper.setEndPage(i); System.out.println(stripper.getText(doc)); }
この時点では以下のようにタブや空白、改行が混じったテキストが抽出される。
【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう 日本Javaユーザグループ 上妻 宜人 (あげつま のりと) はてなブログ : n-agetsuma.hatenablog.com
2. 複数の空白やタブ・改行を半角スペースに置換
Javaで空白を置換する場合、replaceAllに¥sを設定する例が非常に多く紹介されているが、これではうまくいかないことがある。
// タブや改行を空白に置換し、2つ以上スペースが連続する場合は1つに変換 // ¥t タブ, ¥r 復帰, ¥n 改行, ¥r¥n 改行, ¥f 改ページ, 全角スペース String text = stripper.getText(doc).trim() .replaceAll("\\t|\\r|\\n|\\r\\n|\f| ", " "); .replaceAll("\\s{2,}", " ");
JJUG と CCC の間の連続したスペースが消えない。
【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう...
調べてみると、JJUG{¥u0020}{¥u00a0}CCC
となっており、¥u0020はおなじみの半角スペースだが、¥u00a0(No-Break Space)が途中に挟まっている。
¥u00a0(No-Break Space)は、wikipediaに解説があり、HTMLでいう& nbspで、行末にスペースがある場合においてスペースと前の語の間で改行させないために使う文字。スライドの文字列には改行のコントロールが含まれているため、テキスト抽出すると普通のスペースではなく、nbspに変換される場合があるようだ。
他のスライドには同様な文字 ¥u202F (Narrow No-Break Space) も含まれていた。
対処
¥u00a0 (No-Break Space) と ¥u202F(Narrow No-Break Space) もスペースへの置換対象に加えてみた。
String text = stripper.getText(doc).trim() .replaceAll("\\t|\\r|\\n|\\r\\n|\f| |\u00a0|\u202F", " ") .replaceAll("\\s{2,}", " ");
1つの空白区切りで抽出できるようになった。
// before 【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう... // after 【JJUG CCC 2014 Spring H-‐2】 Javaトラブルに備えよう ...