1

ストリームを読み込もうとしましたが、各文字列の正確な位置 (座標) を取得したいと考えていました

    int size = reader.getXrefSize();

    for (int i = 0; i < size; ++i)
    {
        PdfObject pdfObject = reader.getPdfObject(i);
        if ((pdfObject == null) || !pdfObject.isStream())
            continue;

        PdfStream stream = (PdfStream) pdfObject;
        PdfObject obj = stream.get(PdfName.FILTER);

        if ((obj != null) && obj.toString().equals(PdfName.FLATEDECODE.toString()))
        {
            byte[] codedText = PdfReader.getStreamBytesRaw((PRStream) stream);
            byte[] text = PdfReader.FlateDecode(codedText);
            FileOutputStream o = new FileOutputStream(new File("/home..../Text" + i + ".txt"));
            o.write(text);
            o.flush();
            o.close();
        }

    }

私は実際に次のような位置を得ました

......
BT                  
70.9 800.9 Td /F1 14 Tf <01> Tj 
10.1 0 Td <02> Tj               
9.3 0 Td <03> Tj
3.9 0 Td <01> Tj
10.1 0 Td <0405> Tj
18.7 0 Td <060607> Tj
21 0 Td <08090A07> Tj
24.9 0 Td <05> Tj
10.1 0 Td <0B0C0D> Tj
28.8 0 Td <0E> Tj
3.8 0 Td <0F> Tj
8.6 0 Td <090B1007> Tj
29.5 0 Td <0B11> Tj
16.4 0 Td <12> Tj
7.8 0 Td <1307> Tj
12.4 0 Td <14> Tj
7.8 0 Td <07> Tj
3.9 0 Td <15> Tj
7.8 0 Td <16> Tj
7.8 0 Td <07> Tj
3.9 0 Td <17> Tj
10.8 0 Td <0D> Tj
7.8 0 Td <18> Tj
10.9 0 Td <19> Tj
ET
.....

しかし、どの文字列がどの位置に収まるかはわかりません一方、Itextではプレーンテキストを取得できました

PdfReader reader = new PdfReader(new FileInputStream("/home/....xxx.pdf"));
PdfTextExtractor extract = new PdfTextExtractor(reader);

もちろん、まったくポジションなしで....

では、各 text(string,char,...) の正確な位置を取得するにはどうすればよいですか?

4

3 に答える 3

7

plinth と David van Driessche が既に回答で指摘しているように、PDF ファイルからのテキスト抽出は簡単ではありません。幸いなことに、iText のパーサー パッケージのクラスが、面倒な作業のほとんどを行ってくれます。そのパッケージから少なくとも 1 つのクラスが既に見つかりましたPdfTextExtractor,が、このクラスは基本的に、ページのプレーン テキストのみに関心がある場合に iText のパーサー機能を使用するための便利なユーティリティです。あなたの場合、そのパッケージ内のクラスをより詳しく調べる必要があります。

iText を使用したテキスト抽出のトピックに関する情報を取得するための出発点は、セクション 15.3 Parsing PDFs of iText in Action — 2nd Edition、特にextractTextサンプルParsingHelloWorld.javaのメソッドです。

public void extractText(String src, String dest) throws IOException
{
    PrintWriter out = new PrintWriter(new FileOutputStream(dest));
    PdfReader reader = new PdfReader(src);
    RenderListener listener = new MyTextRenderListener(out);
    PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
    PdfDictionary pageDic = reader.getPageN(1);
    PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
    processor.processContent(ContentByteUtils.getContentBytesForPage(reader, 1), resourcesDic);
    out.flush();
    out.close();
}

これはRenderListener実装MyTextRenderListener.javaを利用します:

public class MyTextRenderListener implements RenderListener
{
    [...]

    /**
     * @see RenderListener#renderText(TextRenderInfo)
     */
    public void renderText(TextRenderInfo renderInfo) {
        out.print("<");
        out.print(renderInfo.getText());
        out.print(">");
    }
}

このRenderListener実装は単にテキストを出力するだけですが、検査するTextRenderInfoオブジェクトはより多くの情報を提供します。

public LineSegment getBaseline();    // the baseline for the text (i.e. the line that the text 'sits' on)
public LineSegment getAscentLine();  // the ascentline for the text (i.e. the line that represents the topmost extent that a string of the current font could have)
public LineSegment getDescentLine(); // the descentline for the text (i.e. the line that represents the bottom most extent that a string of the current font could have)
public float getRise()             ; // the rise which  represents how far above the nominal baseline the text should be rendered

public String getText();             // the text to render
public int getTextRenderMode();      // the text render mode
public DocumentFont getFont();       // the font
public float getSingleSpaceWidth();  // the width, in user space units, of a single space character in the current font

public List<TextRenderInfo> getCharacterRenderInfos(); // details useful if a listener needs access to the position of each individual glyph in the text render operation

したがって、RenderListenerテキストを検査することに加えて、またはさらにgetText()考慮し、すべての座標が必要になる可能性があります。getBaseline()getAscentLine()getDescentLine().

PS:のコードのラッパー クラスParsingHelloWorld.extractText()PdfReaderContentParserPdfReader reader,ありますint page,RenderListener renderListener:

PdfReaderContentParser parser = new PdfReaderContentParser(reader);
parser.processContent(page, renderListener);
于 2012-11-30T09:38:56.990 に答える
3

テキスト抽出を行おうとしている場合、これは明らかに重要なプロセスであることに注意してください。少なくとも、RPN マシンを実装してコードを実行し、変換を蓄積し、すべてのテキスト オペレーターを実行する必要があります。現在の一連のページ リソースからフォント メトリックを解釈する必要があり、テキスト エンコーディングを理解する必要がある可能性があります。

私が Acrobat 1.0 に取り組んでいたとき、あなたの問題をサブセットとして含む「検索...」コマンドを担当していました。より豊富なツール セットとより多くの専門知識があれば、それを正しく行うのに数か月かかりました。

于 2012-11-29T21:17:12.467 に答える
1

Tj オペレーターに表示されているバイト数を理解したい場合は、PDF 仕様を参照してください: http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/ PDF32000_2008.pdf

より具体的には、セクション 9.4.3 を見てください。そのセクションを言い換えると、テキストの描画に使用されるフォントで、各バイトまたは潜在的に複数バイトのシーケンスを検索する必要があります (この例では、フォントは /F1 として識別されます)。調べると、このコードが参照している実際の文字が見つかります。

また、ここでこれらのテキスト コマンドが表示される順序は、自然な読み取り順序をまったく反映していない可能性があることに注意してください。そのため、これらの文字の実際の正しい順序が何であるかを見つけた位置に基づいて把握する必要があります。

また、PDF ファイルには、たとえばスペースが含まれていない可能性があることにも注意してください。次の文字を少し右に移動するだけでスペースを「偽装」できるため、一部の PDF ジェネレーターではスペースが省略されます。しかし、座標のギャップを見つけることは言葉の区切りではないかもしれません。たとえば、列の終わりである可能性もあります。

これは非常に困難です。特に、一般的な PDF ファイルでこれを実行しようとしている場合はなおさらです (常に同じソースから作成されていることがわかっている少数のレイアウトの場合とは対照的です)。私はずっと前に、PitStop Pro と呼ばれる製品のために PDF 用のテキスト エディターを作成しましたが、これはまだ存在し (もはや提携していません)、非常に難しい問題でした。

それが可能な場合は、既存のライブラリまたはツールを使用してみてください。そのようなライブラリやツールには確かに商用オプションがあります。私はオープンソース/無料のライブラリにあまり詳しくないので、それについてコメントすることはできません.

于 2012-11-29T23:28:24.370 に答える