Dateiaufbau

Am Hallo Welt Dokument ist sehr schön erkennbar, wie sich das PDF aufteilt. Wir haben einen Kopf, den eigentlichen Dokumentkörper, die Referenztabelle und den Trailer.

Die einzelnen Teile stehen direkt nacheinander in der Datei. Sie müssen durch Zeilenumbrüche getrennt sein. Andere Arten von Leerräumen sind nicht gestattet.

Kopf

Der Kopf steht ganz am Anfang der Datei. Er lautet immer %PDF- gefolgt von der PDF-Versionsnummer.

%PDF-1.4

Körper

Der Dokumentkörper enthält die eigentlichen Informationen zum Dokument. Hierfür werden alle indirekten Objekte des Dokuments hintereinander geschrieben. Die Objekte müssen dabei von 1 an aufsteigend nummeriert sein (ohne Lücken), aber sie müssen nicht unbedingt in der Reihenfolge der Objektnummer in der Datei stehen.

Referenztabelle

Diese Tabelle enthält die Positionen der indirekten Objekte innerhalb der Datei. Die Position ist definiert als Anzahl Bytes zwischen dem Dateianfang und dem ersten Byte des Objekts (0 zeigt also auf das erste Byte der Datei). Dabei gilt die erste Ziffer der ersten Zahl vor dem Schlüsselwort obj als erstes Byte des Objekts. Der Aufbau der Referenztabelle folgt leider nicht den sonst in PDF üblichen Regeln, sondern lautet wie folgt:

Zunächst haben wir eine einzelne Zeile mit dem Wort xref.

Als nächstes folgt eine Zeile mit zwei Zahlen. Die erste Zahl steht für die die erste Objektnummer in der Tabelle. Bei einem neu erstellten PDF ist dies immer 0, auch wenn wir unsere Objekte mit 1 zu nummerieren beginnen. Die zweite Zahl ist die Anzahl der Tabelleneinträge. Dies ist die Anzahl der indirekten Objekte plus 1.

Nun folgt für jeden Tabelleneintrag eine Zeile. Jeder Eintrag besteht aus einer 10-stelligen Nummer, einem Leerschlag, einer 5-stelligen Nummer, noch einem Leerschlag, und einem einzelnen Buchstaben für die Objektart. Die Nummern müssen links mit Nullen aufgefüllt werden. Der Buchstabe ist f für gelöschte (freie) Objekte, und n für normale Objekte.

Falls wir Zeilenumbrüche nach der Unix-Norm oder der alten Apple-Norm verwenden, muss zudem am Ende jeder Tabellenzeile noch ein Leerzeichen stehen. Dies, weil Adobe vorgeschrieben hat, dass jede dieser Zeilen einschliesslich Zeilenumbruch exakt 20 Bytes lang sein muss. Ohne Zeilenumbruch sind die Zeilen 18 Byte lang. Der Windows-Zeilenumbruch braucht 2 Bytes, die anderen hingegen nur 1 Byte.

Der erste Eintrag ist das so genannte Nullobjekt. Dieses ist nur interessant bei der Nachbearbeitung, muss aber auch bei neu erstellen Dokumenten angegeben werden. In diesem Fall ist seine erste Zahl immer 0, die zweite 65535, und der Buchstabe f. Das bedeutet, dass keine gelöschten Objekte existieren.

Danach folgen unsere indirekten Objekte in der Reihenfolge der Objektnummer. Die erste Zahl ist die Position, die zweite die Generationennummer, und der Buchstabe n.

xref
0 7
0000000000 65535 f 
0000000009 00000 n 
0000000050 00000 n 
0000000102 00000 n 
0000000268 00000 n 
0000000374 00000 n 
0000000443 00000 n 

Trailer

Zum Schluss haben wir den Trailer. Dieser ist glücklicherweise wieder etwas „normaler“ aufgebaut.

Als erstes haben wir eine einzelne Zeile mit dem Wort trailer.

Danach folgt ein Dictionary mit einigen Angaben. Dieses braucht mindestens zwei Einträge. /Size, welches die Anzahl Einträge in der Referenztabelle angibt (also die Anzahl indirekter Objekte plus 1), und /Root, welches auf das Katalogobjekt verweist. Zusätzlich hat man in der Regel noch /Info, welches auf das Objekt mit den Metadaten verweist.

Nach dem Dictionary folgt eine einzelne Zeile mit dem Wort startxref, gefolgt wiederum von einer Zeile mit der Position der Referenztabelle. Die Position ist definiert als die Anzahl Bytes zwischen dem Dateianfang und dem x von xref.

Zuletzt steht schliesslich eine Zeile mit dem Text %%EOF. Was nach diesem Text steht, wird ignoriert. Das vermeidet Probleme mit Dateiendesteuerzeichen, überschüssigen Zeilenumbrüchen, etc.

trailer
< < /Size 7
    /Info 1 0 R
    /Root 2 0 R
> >
s tartxref
5 34
%%EOF