PDF ファイル形式
Portable Document Format。Adobe による固定レイアウトの文書標準。
- MIME タイプ
- application/pdf
- 拡張子
- カテゴリ
- ドキュメント
マジックナンバー(ファイル署名)
| 0x00000000 | 255044462D | %PDF- | '%PDF-' + version |
PDF 形式について
PDF の中身は番号の付いたオブジェクト(辞書、配列、ストリーム、数値、文字列)のグラフと、各オブジェクト番号をファイル内のバイトオフセットに対応づける相互参照テーブルです。500 ページの PDF がビューアで一瞬に開くのはこの設計のおかげで、末尾の数百バイトを読んで startxref から相互参照テーブルへ飛び、必要なオブジェクトだけを直接取りに行きます。同時に、PDF が追記にはやたら強く、バイト位置がずれる編集にはやたら弱い理由でもあります。テーブルに入っているオフセットはすべて絶対値だからです。
ヘッダーの構造(バイト単位)
| オフセット | 長さ | フィールド | 意味 |
|---|---|---|---|
| 0 | 5 | %PDF- header marker | ASCII 5 バイトの 25 50 44 46 2D。PDF は最上位のレベルではテキストに近い形式なので、これは文字どおり PostScript 流のコメント行です。パーセント記号がコメント文字であり、PDF を知らないパーサーにとっても 1 行目は合法なテキストになります。 |
| 5 | 3 | Version number | ISO 32000-1 とその前身の Adobe 版なら '1.0' から '1.7'、ISO 32000-2 なら '2.0'。ただしここのバージョンは事実ではなく下限です。文書カタログの /Version キーが上書きして引き上げられるので、1.4 と書かれたファイルが 1.7 の機能を使っていても違反ではありません。 |
| 8 | 1 | Header end-of-line | LF 単体(0A)、CR 単体(0D)、または CR LF の組。組の場合はここが 2 バイトになり、以降がすべて 1 バイトずれます。ヘッダ行にこれ以外のものを置くことは許されていません。 |
| 9 | variable | Binary comment line | ISO 32000-1 の 7.5.2 は、バイナリデータを含むファイルではヘッダの次にコメント行を置き、そこに符号が 128 以上のバイトを 4 つ以上入れることを推奨しています。目的はただ 1 つ、転送ソフトにテキストではなくバイナリだと判断させることです。よくある生成器は %âãÏÓ を書きます。無くても違反ではありませんが、書き手が雑だったことは分かります。 |
| -5 | 5 | %%EOF marker | 整形式のファイルの最終行は 5 バイトの 25 25 45 4F 46 です。後ろに改行が付くこともあるので、読む側は固定位置を信じずに末尾 1024 バイトを後ろ向きに走査します。なお %%EOF が複数あるファイルは壊れているのではなく、増分更新されただけです。 |
| variable | variable | startxref and the trailer | %%EOF の直前に 'startxref' というキーワードが来て、次の行に 10 進のバイトオフセットが入ります。読む側はそこへ飛んで相互参照テーブル(または相互参照ストリーム)を見つけ、そこ経由で /Root、/Info、/Encrypt にたどり着きます。ここまでの何一つ固定位置にはなく、だからこそ末尾のマーカーは走査して探すしかないのです。 |
似た形式との見分け方
| 紛らわしい形式 | 見分け方 |
|---|---|
| PDF/A | PDF/A は長期保存用、PDF/X は印刷入稿用のプロファイルで、どちらもオフセット 0 には痕跡を残しません。準拠レベルは署名ではなくメタデータだからです。PDF/A のファイルは XMP メタデータストリームの中で pdfaid 名前空間を使って part と conformance level を宣言し、さらに全フォントの埋め込みと output intent が必須です。つまり XMP で PDF/A を名乗っていても検証に落ちることはあり得ますし、ヘッダはどちらとも教えてくれません。 |
| Encrypted PDF | これも先頭バイトは同じ。手がかりはファイル末尾の trailer 辞書にある /Encrypt キーです。実務上 PDF の暗号化がたいてい何を意味するかは知っておく価値があります。ユーザーパスワードが空でオーナーパスワードだけの権限制御であることが多く、その場合、中身は完全に読めていて、印刷やコピーの制限はビューアが行儀よく従っているだけです。ストリームまで暗号化するユーザーパスワードとは別物です。 |
| OLE2 / CFB | 「文書を送って」と言われたときに出てくる 2 つの選択肢です。2007 年より前の Word ファイルは D0 CF 11 E0 で始まる Compound File Binary コンテナ、PDF は %PDF-。後工程で効く違いは、PDF がページ上のグリフ位置を固定するのに対し .doc は固定しないこと。フォントが無いマシンで .doc がレイアウト崩れを起こし、PDF は崩れないのはそのためです。 |
| PostScript | PDF の直系の祖先で、オブジェクト構文もコメント文字も同じなので今も混同されます。PostScript ファイルは '%!PS-Adobe-' で始まり、EPS も同様ですが前にバイナリプレビューのヘッダ C5 D0 D3 C6 が付くことがあります。PostScript は上から下へ実行される完全なプログラミング言語、PDF はランダムアクセスできる静的なオブジェクトグラフ。PDF が PostScript を置き換えた理由そのものです。 |
よくある壊れ方
- バイト位置がずれる編集。相互参照テーブルは絶対バイトオフセットを持つので、ファイルのどこかに 1 バイト挿入・削除しただけで、それ以降のエントリが全部無効になります。ビューアはテーブルを作り直して(ファイル全体を走査して 'N 0 obj' のパターンを拾って)対処するので、手で編集した PDF はすっと開かず、警告付きで遅れて開きます。
- ダウンロードの途中切れ。前方のオブジェクトは残っているので、テーブルを再構築すれば 1〜2 ページは描画できることもありますが、末尾の相互参照テーブルと trailer は失われており、読む側には出発点がありません。確認するのは末尾 1024 バイトに %%EOF があるかどうかです。
- テキストモード転送。ASCII モードの FTP は FlateDecode ストリーム内の 0D 0A を書き換えます。ヘッダは無傷でパースも通るのでファイルは開き、そのうえで個々のページが真っ白になったりストリームのデコードエラーを出したりします。deflate データが展開できなくなっているからです。
- 増分更新を間違ったベースにつなげた。PDF は全体を書き直さずに変更を追記できるので、署名や注釈の付いたファイルは元のファイル+前を指す 2 つ目の相互参照セクションという構造になっています。/Prev のオフセットが実際の前の %%EOF の位置と合わないセクションを継ぎ足すと鎖が切れます。それでもヘッダも最終 trailer も無傷に見えてしまいます。
- 相互参照ストリームを書きながらバージョンを 1.4 と名乗る生成器。圧縮された相互参照ストリームとオブジェクトストリームは PDF 1.5 からの機能です。宣言されたバージョンを額面どおり守る読み手はそれを探しに行かないので、全バイトが正しく揃っているのに文書にはオブジェクトが 1 つも無いように見えます。
この形式の現在地
見た目が変わってはいけない文書を渡す手段として広く通用するのは、30 年経った今も PDF だけです。契約書、請求書、明細、論文、申請書、印刷入稿データ、署名や長期保存が要るものは結局すべて PDF になります。フォントを埋め込み、字の位置をページ上で固定してしまい、読み手の環境に合わせて流し直したりしないからです。逆に向いていないのは、また編集する予定のあるものです。PDF が持っているのは段落ではなく描画命令なので、「PDF を編集する」とは文字の並びから単語を推測し直す作業になります。スマホで読むものにも向きません。固定された A4 ページはちょうど形が合わず、リフローできる EPUB のほうが圧倒的に有利です。派生規格はそれぞれ確固たるニッチを持っていて、長期保存向けの PDF/A はフォントの完全埋め込みを求め外部依存を許さず、PDF/X は印刷入稿用です。仕様は今や Adobe ではなく ISO のもので、ブラウザも自前のレンダラーを積んでいます。何もインストールせずどの端末でも確実に開ける、数少ないファイル形式の 1 つです。
PDF ファイルをこのサイトで開く
どれもブラウザ内で動きます。ファイルが端末から出ることはありません。
関連する形式
PDF と混同しやすい形式です。先頭バイトを見比べてください。
| 形式 | 先頭バイト | 拡張子 |
|---|---|---|
| OLE2 / CFB | D0 CF 11 E0 A1 B1 | .doc |
| RTF | 7B 5C 72 74 66 31 | .rtf |
| Word 文書(docx) | 50 4B 03 04 | .docx |