9.1.1 抽出する文字に含まれた全角スペースを半角スペースに置き換える

ExtTextWithRplcIdeographicSpaceToSpace_Top

狙い・効果

PDFから文字抽出抽出する文字列に全角スペースが含まれていた場合、半角のスペースに置き換えます。

処理の概要

PDFから抽出する文字列の中に和字間隔が混ざっていたら、スペース(Unicode 0020)に置き換えることができます。和字間隔はIDEOGRAPHIC SPACEと呼ばれ、日本語の環境では一般に全角スペースとして使われている文字のことです。以降、「和字間隔」のことを「全角スペース」と表記します。

PtlParamExtractText.setUnicodeToSpace()を使用します。
AHEXTRACTTEXT_UNI_IDEOGRAPHIC_SPACEを指定することで、抽出した文字列に含まれた全角スペースを半角のスペースに置き換えます。置き換える特殊文字の指定はint型フラグで行います。

サンプルプログラムでは、入力PDFの指定したページ全体から文字列を抜き出す際に、指定可能な特殊文字について削除する・しないを切り替えた上で抽出します。

『PDF Tool API』の主な機能

表9.2 AHEXTRACTTEXT_UNI_***の種別
列挙型定数
特殊文字の種別 -> ユニコード
AHEXTRACTTEXT_UNI_C0_CONTROLS 
C0制御文字 -> U+0000-U+001F
AHEXTRACTTEXT_UNI_SPACE
単体のスペース -> U+0020
AHEXTRACTTEXT_UNI_NO_BREAK_SPACE
ノーブレークスペース-> U+00A0
AHEXTRACTTEXT_UNI_SOFT_HYPHEN
ソフトハイフン-> U+00AD
AHEXTRACTTEXT_UNI_SPACES
UnicodeのU+2000~U+200Bの 主に“Spaces” カテゴリに含まれる特殊スペース -> U+2000-U+200B
AHEXTRACTTEXT_UNI_IDEOGRAPHIC_SPACE
全角スペース-> U+3000
AHEXTRACTTEXT_UNI_VARIATION_SELECTOR
異体字セレクタ-> U+FE00-U+FE0F
AHEXTRACTTEXT_UNI_REPLACEMENT_CHARACTER
置き換え文字 -> U+FFFD
AHEXTRACTTEXT_UNI_ALL
上記全てを対象とする(今後のバージョンアップでフラグが増えたらそれも含む)。

プログラム例

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 ExtTextWithRplcIdeographicSpaceToSpace {

    // そのクラスのusageを表示する関数
    private static void printUsage() {
        System.out.println("usage: java ExtractTextWithReplacingSpecialCharToSpace in-pdf-file out-text-file"
                         + " page-to-extract rplc-ideographic-space");
        System.out.println("--以下の文字に対して、[0:スペースに置き換えない  1:置き換える]を選択--");
        System.out.println("rplc-ideographic-space : 全角スペース");
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (args.length < 4) {
            printUsage(); // usageメッセージの表示
            return;
        }

        // コマンドライン引数の読み取り・判定
        // 出力PDFの名前はあとで渡すためにString型で保存する。
        String outputTextURI = args[1];
        int pageToExtract = Integer.parseInt(args[2]);
        boolean rplcIdeographicSpace = false;
        int unicodeCharFlag = 0;

        //各種削除フラグの読み取り判定
        //rplc-ideographic-space
        try {
            rplcIdeographicSpace = readBoolArgs(args[3],
                                              "rplc-ideographic-spaceは" +
                                              "0か1で指定してください。");
        }
        catch (IllegalArgumentException ex) {
            System.out.println(ex.getMessage());
            printUsage(); // usageメッセージの表示
            return;
        }

        //各フラグの論理和をunicodeCharFlagに設定
        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のエラー処理
                        System.out.println("ERROR: page-to-extractはPDFの総ページ数より"+
                                           "小さい値を指定してください。");
                        System.out.println("総ページ数:" + wholePageNum);
                        printUsage();
                        throw new Error("ERROR: page-to-extractはPDFの総ページ数より"+
                                        "小さい値を指定してください。");
                    }
                    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を返す関数】...
    }
}

プログラムファイル名

ExtTextWithRplcIdeographicSpaceToSpace.java

入出力操作の例

C:\samples>java cookbook.ExtTextWithRplcIdeographicSpaceToSpace 
usage: java ExtractTextWithReplacingSpecialCharToSpace in-pdf-file out-text-file page-to-extract rplc-ideographic-space
--以下の文字に対して、[0:スペースに置き換えない  1:置き換える]を選択--
rplc-ideographic-space : 全角スペース

C:\samples>java cookbook.ExtTextWithRplcIdeographicSpaceToSpace Special_letter_sample_IdeographicSpace.pdf Output_ExtTextWithRplcIdeographicSpaceToSpace.txt 0 1 
1ページ目のテキストを抽出します。
特殊文字一覧IDEOGRAPHIC SPACEIDEOGRAPHIC SPACE(U3000) ishere" ""The quick brown fox jumps over the lazy dog"
Output text URI :Output_ExtTextWithRplcIdeographicSpaceToSpace.txt
-- 完了 --

この操作例では例文の空白がすべてIDEOGRAPHIC SPACEのPDFが使われています。

5-9-1-1_ExtTextWithRplcIdeographicSpaceToSpace_03

図9.1 入力PDFの例

下図はIDEOGRAPHIC SPACEを半角スペースに置き換えた場合とそのままの状態の比較です。

5-9-1-1_ExtTextWithRplcIdeographicSpaceToSpace_01

図9.2 操作例の出力テキスト。全角スペース(IDEOGRAPHIC SPACE)を半角スペースに置き換えている

5-9-1-1_ExtTextWithRplcIdeographicSpaceToSpace_00

図9.3 全角スペースをそのまま残した例