PDFから文字抽出抽出する文字列に含まれた特殊なスペースを半角スペースに置き換えます。
第1項では全角スペースを半角スペースに置き換えましたが、『PDF Tool API』はUnicodeのU+2000~U+200Bから、主に“Spaces”カテゴリに含まれる特殊スペースを置き換え対象にすることができます。(表9.3)
PtlParamExtractText.setUnicodeToSpace()でAHEXTRACTTEXT_UNI_SPACESを対象にすることで、抽出した文字列に含まれた特殊スペースを半角スペースに置き換えます。置き換える特殊文字はint型フラグで指定します。
Unicode | 表示名 | 内容 |
---|---|---|
U+2000 | En Quad | en幅(文字の高さの半分)のスペース。一般にU+2002と同等に扱われる。(U+2002が推奨) |
U+2001 | Em Quad | em幅(文字の高さと同等)のスペース。一般にU+2003と同等に扱われる。(U+2003が推奨) |
U+2002 | En Space | en幅のスペース。一般にU+2000と同等だがこちらが推奨される。 |
U+2003 | Em Space | em幅のスペース。一般にU+2001と同等だがこちらが推奨される。 |
U+2004 | Three-Per-Em Space | em幅の1/3のスペース。“thick space” の名称で知られる。 |
U+2005 | Four-Per-Em Space | em幅の1/4のスペース。“mid space” の名称で知られる。 |
U+2006 | Six-Per-Em Space | em幅の1/6のスペース。U+2009と同等に扱われることがある。 |
U+2007 | Figure Space | 数字1つの幅に等しいスペースで、フォントにより幅が変化することがある。別名“numeric space” |
U+2008 | Punctuation Space | ピリオド、またはカンマの送り幅に等しいスペース。 |
U+2009 | Thin Space | em幅の1/5, または1/6のスペース。千、百万といった数値を千ずつで区切る際の文字として用いられることがある。 |
U+200A | Hair Space | Thin Space(U+2009)よりも狭い空白。 |
U+200B | Zero Width Space | ゼロ幅のスペース。単語間で目に見えるスペースがない言語などで単語の区切りをマークされるために用いられる。 |
サンプルプログラムでは、入力PDFの指定したページ全体から文字列を抜き出す際に上記の特殊スペースに加え、ノーブレークスペース、全角スペースについてそれぞれ半角スペースに置換する/しないを切り替えた上で抽出します。
package cookbook; import java.io.BufferedWriter; import java.io.PrintWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.charset.StandardCharsets; import jp.co.antenna.ptl.*; public class ExtTextWithRplcSpecialSpaceToSpace { // そのクラスのusageを表示する関数 private static void printUsage() { System.out.println("usage: java ExtTextWithRplcSpecialSpaceToSpace in-pdf-file" + " out-text-file page-to-extract rplc-space rplc-no-break-space" + " rplc-spaces rplc-ideographic-space"); System.out.println("--以下の各文字に対して、[0:スペースに置き換えない 1:置き換える]を選択--"); System.out.println("rplc-space : スペース"); System.out.println("rplc-no-break-space : ノーブレークスペース"); System.out.println("rplc-spaces : 特殊スペース"); System.out.println("rplc-ideographic-space : 全角スペース"); } /** * @param args the command line arguments */ public static void main(String[] args) { if (args.length < 7) { printUsage(); // usageメッセージの表示 return; } // コマンドライン引数の読み取り・判定 // 出力PDFの名前はあとで渡すためにString型で保存する。 String outputTextURI = args[1]; int pageToExtract = Integer.parseInt(args[2]); boolean rplcSpace = false; boolean rplcNoBreakSpace = false; boolean rplcSpaces = false; boolean rplcIdeographicSpace = false; int unicodeCharFlag = 0; //各種削除フラグの読み取り判定 //rplc-space try { rplcSpace = readBoolArgs(args[3], "rplc-spaceは" + "0か1で指定してください。"); } catch (IllegalArgumentException ex) { System.out.println(ex.getMessage()); printUsage(); // usageメッセージの表示 return; } //rplc-no-break-space try { rplcNoBreakSpace = readBoolArgs(args[4], "rplc-no-break-spaceは" + "0か1で指定してください。"); } catch (IllegalArgumentException ex) { System.out.println(ex.getMessage()); printUsage(); // usageメッセージの表示 return; } //rplc-spaces try { rplcSpaces = readBoolArgs(args[5], "rplc-spacesは" + "0か1で指定してください。"); } catch (IllegalArgumentException ex) { System.out.println(ex.getMessage()); printUsage(); // usageメッセージの表示 return; } //rplc-ideographic-space try { rplcIdeographicSpace = readBoolArgs(args[6], "rplc-ideographic-spaceは" + "0か1で指定してください。"); } catch (IllegalArgumentException ex) { System.out.println(ex.getMessage()); printUsage(); // usageメッセージの表示 return; } //各フラグの論理和をunicodeCharFlagに設定 if(rplcSpace) { unicodeCharFlag = unicodeCharFlag | PtlParamExtractText.AHEXTRACTTEXT_UNI_SPACE; } if(rplcNoBreakSpace) { unicodeCharFlag = unicodeCharFlag | PtlParamExtractText.AHEXTRACTTEXT_UNI_NO_BREAK_SPACE ; } if(rplcSpaces) { unicodeCharFlag = unicodeCharFlag | PtlParamExtractText.AHEXTRACTTEXT_UNI_SPACES; } if(rplcIdeographicSpace) { unicodeCharFlag = unicodeCharFlag | PtlParamExtractText.AHEXTRACTTEXT_UNI_IDEOGRAPHIC_SPACE; } try(PtlParamInput inputFile = new PtlParamInput(args[0]); PtlPDFDocument doc = new PtlPDFDocument()) { // PDFファイルをロード doc.load(inputFile); try(PtlPages pages = doc.getPages()) {//ページコンテナの取得 // ページコンテナが空かどうか if(pages.isEmpty()) { System.out.println("ERROR : ページコンテナが空"); throw new Error("ERROR : ページコンテナが空"); } //ページ数を取得 int wholePageNum = doc.getPageCount(); //pageToExtractが0ならすべてのページを処理する if(pageToExtract == 0) { StringBuilder wholeTextFromPdf = new StringBuilder(); // ページの取得(パラメータindexは0が先頭のため1を引く) for(int i = 0; i < wholePageNum; i++) { try(PtlPage page = pages.get(i); PtlContent content = page.getContent()) { // ページコンテントの取得 System.out.println((i+1) + "ページ目のテキストを抽出します。"); wholeTextFromPdf.append(extractTextSetReplaceUnicodeFlag(unicodeCharFlag, content)); } } outputTextFile(outputTextURI, wholeTextFromPdf.toString()); }else { if(wholePageNum < pageToExtract) { //pageToExtractのエラー処理 ...【ExtTextWithRplcIdeographicSpaceToSpace.javaと同じ処理のため省略 ・総ページ数よりも大きいページ数を指定した場合のエラー処理】... } try(PtlPage page = pages.get(pageToExtract - 1); //指定したページを取得する PtlContent content = page.getContent()) { System.out.println(pageToExtract + "ページ目のテキストを抽出します。"); outputTextFile(outputTextURI, extractTextSetReplaceUnicodeFlag(unicodeCharFlag, content)); } } } } ...【GetPDFVersion.javaと同じ処理のため省略 ・エラーメッセージ処理と出力】... } private static String extractTextSetReplaceUnicodeFlag(int unicodeCharFlag, PtlContent content) throws IOException, PtlException, Exception, Error { try(PtlParamExtractText paramExtractText = new PtlParamExtractText()) { // 文字抽出のパラメータクラス。 //setUnicodeToRemoveをパラメータに設定 paramExtractText.setUnicodeToSpace(unicodeCharFlag); // 文字列抽出 String textFromPdf = content.extractText(paramExtractText); System.out.println(textFromPdf); // 抽出した文字列を返す return textFromPdf; } } /** * テキストファイルを出力するための関数。 * 出力エンコードはUTF-8を指定する。 * 特に外部からの呼び出しを想定しないためprivateとする。 * * @param outputTextURI 出力ファイルのURI。 * @param TextFromPdf 出力したいString型変数 */ private static void outputTextFile(String outputTextURI, String TextFromPdf){ ...【ExtractTextSetRect.javaと同じ処理のため省略 ・outputTextURIのパスにTextFromPDFの内容をUTF-8エンコーディングで出力する処理】... } /** * 0または1を入力されたargsにより、trueまたはfalseを返すメソッド。 * * @param args 与えられるコマンドライン引数。0または1でtrueまたはfalseを指定する。 * @param errorMessage argsが0か1でなかった場合に出力されるエラーメッセージを指定する。 * @return argsの数値を読み取った結果を戻す * @throws java.lang.IllegalArgumentException argsが0か1でなかった場合に発生。 */ public static boolean readBoolArgs(String args, String errorMessage) throws IllegalArgumentException { ...【FixUpPDFASetSaveOption.javaと同じ処理のため省略 ・0または1を読み取り、boolean型のfalseまたはtrueを返す関数】... } }
ExtTextWithRplcSpecialSpaceToSpace.java
C:\samples>java cookbook.ExtTextWithRplcSpecialSpaceToSpace usage: java ExtTextWithRplcSpecialSpaceToSpace in-pdf-file out-text-file page-to-extract rplc-space rplc-no-break-space rplc-spaces rplc-ideographic-space --以下の各文字に対して、[0:スペースに置き換えない 1:置き換える]を選択-- rplc-space : スペース rplc-no-break-space : ノーブレークスペース rplc-spaces : 特殊スペース rplc-ideographic-space : 全角スペース C:\samples>java cookbook.ExtTextWithRplcSpecialSpaceToSpace Special_letter_sample_specialSpaces.pdf Output_ExtTextWithRplcSpecialSpaceToSpace.txt 0 1 1 1 1 1ページ目のテキストを抽出します。 特殊文字一覧SPACEspace(U0020) is here " ""The quick brown fox jumps overthe lazy dog"NO_BREAK_SPACENO-Break space(U00A0) is here" ""The quick brown fox jumps over the lazy dog"NO-Break space(nbsp) is here " ""The quick brown fox jumps over the lazy dog"Special SpacesEn Quad(U2000) is here" ""The quick brown fox jumps over the lazy dog"Em Quad(U2001) is here" ""The quick brown fox jumps over the lazy dog"En Space(U2002) is here" ""The quick brown fox jumps over the lazy dog" [...後略...] Output text URI :Output_ExtTextWithRplcSpecialSpaceToSpace.txt -- 完了 --
この操作例では例文の空白がそれぞれの該当する特殊スペースになったPDFが用意されています。コマンドライン上でプログラムを実行した場合、コマンドラインの文字コードで表示できない特殊スペースは出力ログ上では「?」として表示されるときがあります。
次は特殊スペースをすべて半角スペースに置き換えた例と置き換えなかった例の比較です。