1

pdfbox を使用して、pdf に埋め込まれた画像の画像メタデータ (および画像) を抽出しようとしています。次の問題があります。

for each page i:
 for each image j in page i:
  extract metadata, output
  create the image file in separate thread

generate_image()これで、イメージ ファイルを作成するための次のコードが得られました。このコードは、 in FileWritingclass implementationと呼ばれるメソッドに含まれていますRunnable。このメソッドは から呼び出されrun()ます。コードは次のとおりです。

try {
    File F=new File(figurename);
    item.getImage().write2file( F );


} catch (Exception e) {
    e.printStackTrace();
} 

whereはオブジェクトをitem.getImage()返しPDXObjectImageます。別のスレッドを作成せずにこれを行うと問題なく動作しますが、このタスクを実行するスレッドを作成すると、次のエラーが表示されます。

java.lang.IndexOutOfBoundsException: Index: 5, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
at org.apache.pdfbox.io.RandomAccessBuffer.seek(RandomAccessBuffer.java:84)
at org.apache.pdfbox.io.RandomAccessFileInputStream.read(RandomAccessFileInputStream.java:96)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at org.apache.pdfbox.pdmodel.graphics.xobject.PDCcitt$TiffWrapper.read(PDCcitt.java:468)
at org.apache.pdfbox.io.IOUtils.copy(IOUtils.java:68)
at org.apache.pdfbox.pdmodel.graphics.xobject.PDCcitt.write2OutputStream(PDCcitt.java:184)
at org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage.write2file(PDXObjectImage.java:165)
at extractor.FileWriting.generate_image(FileWriting.java:136)

誰かが私が間違っているところを指摘できますか?

4

1 に答える 1

3

あなたの問題は、複数のスレッドで同じ pdfbox クラスを使用していることだと思います。

PDFBox の古いバージョンでは、FAQ ページに次のように記載されていました。

PDFBox はスレッドセーフですか?

いいえ!一度に 1 つのドキュメントにアクセスできるスレッドは 1 つだけです。それぞれ独自の PDDocument オブジェクトにアクセスする複数のスレッドを持つことができます。

ただし、2.0 以降 (おそらく?) では、PDFBox の FAQ ページに次のように記載されています。

PDFBox は、異なるスレッドから同じ PDDocument に対する読み取り専用操作を実験的にサポートしています。

ただし、現在 (2019 年 6 月) の議論を考えると、これは有望ではないようです。したがって、エッジで生活したくない場合でも、使用しているクラスを使用しThreadLocalて保持することを検討する必要があります。PDDocument何かのようなもの:

private ThreadLocal<PDDocument> localPdDocument = new ThreadLocal<PDDocument>() {
    @Override
    protected PDDocument initialValue() {
        return new PDDocument();
    }
};

...
PDDocument doc = localPdDocument.get();
...
于 2013-01-25T22:15:33.583 に答える