readPages の (java、申し訳ありません) ソースは次のとおりです。
protected internal void ReadPages() {
catalog = trailer.GetAsDict(PdfName.ROOT);
rootPages = catalog.GetAsDict(PdfName.PAGES);
pageRefs = new PageRefs(this);
}
trailer,
catalog ,
rootPages , and
pageRefs` はすべて PdfReader のメンバー変数です。
PDF のトレーラーまたはルート/カタログ オブジェクトが単に欠落している場合、PDF は本当にひどく壊れています。外部参照テーブルが少しずれている可能性が高く、問題のオブジェクトが本来あるべき場所に正確に配置されていません (これは悪いことですが、回復可能です)。
ただし、PdfReader が最初に PDF を開くと、ファイル内のすべてのオブジェクトが解析され、適切な PdfObject 派生クラスに変換されます。
実行していないのは、外部参照テーブルによって要求されたオブジェクト番号と、ファイルから読み込まれたオブジェクト番号が実際に一致することを確認することです。可能性は低いですが、可能です。悪いソフトウェアは、PDF オブジェクトを間違った順序で書き出す可能性がありますが、外部参照テーブルのバイト オフセットは正しく維持します。外部参照テーブルのオブジェクト番号を、ファイル内の特定のバイト オフセットの番号で上書きするソフトウェアは問題ありません。
iTextは問題ありません。
PDFも見たいです。
うん。そのPDFは大丈夫です。具体的には:
ファイルの最初の 70kb 程度は、きれいな小さな PDF を定義します。その後、変更が PDF に追加されました。
それを確認します。誰かが PDF に変更を追加しようとして失敗しました。ひどく。どれほどひどいものかを理解するために、次の例を使用して、PDF の内部構文のいくつかを説明しましょう。
%%PDF1.6
1 0 obj
<</Type/SomeObject ...>>
endobj
2 0 obj
<</Type/SomeOtherObj /Ref 1 0 R>>
endobj
3 0 obj
...
endobj
<etc>
xref
0 10
0000000000 65535 f
0000000010 00001 n
0000000049 00002 n
0000000098 00003 n
...
trailer
<</Root 4 0 R /Size 10>>
startxref 124
%%EOF
したがって、ヘッダー/バージョン「%%PDF1.v」、オブジェクトのリスト (ここでは辞書と呼ばれます)、リスト内のすべてのオブジェクトのバイト オフセットとオブジェクト番号をリストするクロス (x) 参照テーブルがあります。ルート オブジェクトと PDF 内のオブジェクト数、および「xref」の「x」へのバイト オフセットを示すトレーラー。
既存の PDF に変更を追加できます。これを行うには、既存の %%EOF の後に新しいオブジェクトまたは変更されたオブジェクトを追加し、それらの新しいオブジェクトへのクロス リファレンス テーブルとトレーラを追加します。追加された変更のトレーラには、前の相互参照テーブルへのバイト オフセットを持つ /Prev キーが含まれている必要があります。
あなたの NOT-OKAY pdf で、誰かが PDF に変更を追加しようとしましたが、ひどく失敗しました。
元の PDF はそのまま残っています。それが Reader に表示されるものであり、PDF を保存すると得られるものです。16 進エディタで最初の %%EOF の後にあるものをすべてハッキングしたところ、ファイルは問題ありませんでした。
したがって、NOT-OKAY pdf のレイアウトは次のとおりです。
%PDF1.4.1
1 0 obj...
2 through 7
xref
0 7
<healthy xref>
trailer <</Size 8 /Root 6 0 R /Info 7 0 R>>
startxref 68308
%%EOF
ここまでは順調ですね。ここで物事が醜くなります
<binary garbage>
endstream
endobj
xref
0 7
<horribly wrong xref>
trailer <</ID [...] /Info 1 0 R /Root 2 0 R /Size 7>>
startxref 223022
%%EOF
そのセクションで正しいのは、startxref の値だけです。
問題:
- 2 番目のトレーラーには /Prev キーがありません。
- 2 番目の外部参照テーブルのすべてのバイト オフセットが間違っています。
- は「ストリーム」オブジェクトの一部ですが、そのオブジェクトの先頭が欠落しています。ストリームは次のようになります
1 0 obj
<</Type/SomeType/Length 123>>
stream
123 bytes of data
endstream
endobj
このファイルの最後は、(圧縮された)ストリームの一部で構成されています...しかし、最初に辞書がなく、使用しているフィルターとその長さを示しています(欠落しているデータは言うまでもありません) )、それでは何もできません。
誰かがこの PDF を完全に再構築しようとして、誤って元の 70kb をバージョンの先頭に上書きしたのではないかと思います。カブーム。
アドビは、追加された不適切な変更を単に無視しているように見えます。iText もこれを行うことができますが、次のこともできます。
iText が PDF を開くのに失敗した場合:
1.ファイルを逆方向に検索して、最後から 2 番目を探します%%EOF
。最後にあるものは無視して、ファイルの以前の状態が必要です。2. 最後から 2 番目以降 (存在する場合) をすべて削除し、%%EOF
もう一度開いてみます。
悲しいことに、この壊れた PDF は「元の」 70kb とは完全に異なっていた可能性があり、IO エラーによってファイルの最初の部分が上書きされた可能性があります。可能性は低いですが、確実な方法はありません。