LoginSignup
8
8

More than 5 years have passed since last update.

PDFファイルのチェック

Last updated at Posted at 2017-07-14

PDFファイルの末尾には決まった構造があります。これを確認することで、ファイルが途中で切れていないかを簡単にチェックできます。

必要最低限の構造だけを説明します。これだけではPDFの仕様を理解するには不足ですが、取っ掛かりにはなるかもしれません。

構造

PDFファイルの基本的な部分はテキストで記述されます。

※ ストリームという構造があり、その中にバイナリが直接埋め込まれます。今回の範囲を超えるため詳細は省略します。

最低限の構造を持った白紙のPDFファイルを示します。テキストエディタで打ち込んで改行コードをCRLFで保存すれば、PDFファイルとして開けます。

blank.pdf
%PDF-1.2
1 0 obj <</Type/Catalog/Pages 2 0 R>> endobj
2 0 obj <</Type/Pages/Count 1/Kids [3 0 R]>> endobj
3 0 obj <</Type/Page/Parent 2 0 R>> endobj
xref
0 4
0000000000 65535 f
0000000010 00000 n
0000000056 00000 n
0000000109 00000 n
trailer <</Root 1 0 R/Size 4>>
startxref
153
%%EOF

次の構造になっていることが分かります。

  1. シグネチャ %PDF-1.2
  2. オブジェクトの羅列 番号 0 obj ... endobj
  3. クロスリファレンス xref
  4. トレイラー trailer
  5. クロスリファレンスのオフセット startxref
  6. 番兵 %%EOF

xreftrailer はオブジェクトの1つとして埋め込まれている場合がありますが、startxref%%EOF は必ず末尾に存在します。

※ 編集時に差分が追記されることがあり、%%EOF などがファイルの途中にも存在することがあります。今回の範囲を超えるため詳細は省略します。

チェック

ファイルの末尾の startxref を確認することで、ファイルが途中で切れていないかを簡単にチェックできます。

F# で startxref の値を取得する例を示します。

open System
open System.IO
open System.Text

let readStartXref f =
    use fs = new FileStream(f, FileMode.Open)
    let bytes = Array.zeroCreate<byte> 64
    let pos = max 0L (fs.Length - int64 bytes.Length)
    fs.Position <- pos
    let size = fs.Read(bytes, 0, bytes.Length)
    let text = Encoding.ASCII.GetString(bytes, 0, size)
    let p = text.LastIndexOf "startxref" |> int64
    if p < 0L then p else
    fs.Position <- pos + p
    use sr = new StreamReader(fs, Encoding.ASCII)
    try
        ignore <| sr.ReadLine()
        Int64.Parse(sr.ReadLine())
    with _ -> -1L

とりあえずファイルが途中で切れていないかを確認するだけなら、これで用は足ります。

しかし正確には startxref のオフセットを取得するだけでは不足で、

  • オフセットが正常な範囲内か
  • 指す先にクロスリファレンスが存在しているか
  • クロスリファレンスが正常な形式か

などをチェックする必要があります。そのためにはクロスリファレンスのパーサーを実装する必要があります。

※ クロスリファレンスがオブジェクトに埋め込まれている場合、圧縮データを展開する必要があります。今回の範囲を超えるため詳細は省略します。

GUI

手軽にチェックするための簡易GUIです。

参考

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8