A PDF 1.0 to 1.4 file has four parts, in this order: a header line, a body of objects, a cross-reference table that gives the byte offset of every object, and a trailer that names the document’s root and says where the table starts. A reader starts at the end of the file, not the beginning. Every object stands alone in the body as text and, for streams, raw bytes; none is packed inside another.
0Header%PDF-1.4, then a comment of binary bytestwo lines…Body indirect objects,1 0 obj … endobj, in any ordermost of the file…Cross-reference tablexref, then one 20-byte line per object20 bytes an object…Trailertrailerand a dictionary,startxref, an offset,%%EOFa few lines
A real file
A small PDF 1.3 file of 2,065 bytes, a one-page icon written by the macOS graphics system. Its header and binary comment come first, then object 4, the page’s compressed content stream:
00000000 25 50 44 46 2D 31 2E 33 0A 25 C4 E5 F2 E5 EB A7 %PDF-1.3.%......
00000010 F3 A0 D0 C4 C6 0A 34 20 30 20 6F 62 6A 0A 3C 3C ......4 0 obj.<<
00000020 20 2F 4C 65 6E 67 74 68 20 35 20 30 20 52 20 2F /Length 5 0 R /
The end of the same file, as text. The table lists objects 0 to 11, the trailer
names object 11 as the catalog, and startxref says the table begins
at byte 1,668:
xref
0 12
0000000000 65535 f
0000001528 00000 n
0000000205 00000 n
0000001397 00000 n
0000000022 00000 n
0000000187 00000 n
0000000307 00000 n
0000001362 00000 n
0000000403 00000 n
0000000448 00000 n
0000001342 00000 n
0000001478 00000 n
trailer
<< /Size 12 /Root 11 0 R /Info 1 0 R /ID [ <EDF3E29C9D9811DA8A2D000D9370ACB8>
<EDFAECC19D9811DA8A2D000D9370ACB8> ] >>
startxref
1668
%%EOF
Header
The first line of the file is %PDF- and the version: %PDF-1.0,
%PDF-1.1, %PDF-1.2, %PDF-1.3 or
%PDF-1.4. It is a comment, so a reader that looks for objects skips
it. The version is the one the file was written to, and a reader should expect
nothing newer in it.
From PDF 1.4 the document catalog may hold a Version name, such as
/1.4. If it is later than the header’s version, it wins. This lets an
incremental update raise the version without rewriting the first line. A reader
should not refuse a file only because the version is newer than it knows; it reads
what it can.
The header is meant to be at byte 0. Readers such as Acrobat also accept it a little way into the file, within the first 1,024 bytes, which happens when a mail gateway or a download tool puts something in front of it. The offsets in the table are then out by the length of what was put in front, and readers that allow for this correct them.
Binary comment
PDF 1.0 files were plain 7-bit text, with binary data written out in ASCII85 or
hexadecimal. From PDF 1.1 streams may hold raw binary bytes. A file with binary data
should have, on the line after the header, a comment of at least four bytes with
values of 128 or more, such as %âãÏÓ (25 E2 E3 CF D3).
Programs that move files about, such as old mail and FTP tools, look at the first
bytes to decide whether a file is text, and these bytes tell them it is not.
The comment has no meaning to a PDF reader, which skips it like any other comment. Writers pick their own bytes; the example above has eleven.
Body
The body is a run of indirect objects, each written
12 0 obj
<< /Type /Page /Parent 3 0 R /MediaBox [0 0 612 792] /Contents 13 0 R >>
endobj
The first number is the object number, a positive integer, and the second the
generation number, 0 for every object of a new file. Objects can come in any order
and need not be numbered without gaps. They point at each other with references
such as 3 0 R. A stream object is a dictionary followed by
stream, its bytes and endstream, all inside
obj … endobj. See Objects
and syntax for every kind of object.
Comments, which start with % and run to the end of the line, can
appear between objects and are ignored. White space between objects is free.
Cross-reference table
After the body comes the table, starting with the keyword xref on a
line of its own. It is made of subsections, each a line with the first object
number and a count, then one entry of exactly 20 bytes for each object:
xref
0 3
0000000000 65535 f
0000000017 00000 n
0000000081 00000 n
An in-use entry, ending n, gives the object’s byte offset (ten digits)
and generation (five digits). A free entry, ending f, gives the next
free object number instead. Because every entry is the same length, a reader can
find the entry for any object by arithmetic. The details, with the free list, are on
Cross-reference and
trailer.
Trailer
The keyword trailer and a dictionary follow the table. Its keys are:
| Key | Type | Since | Meaning |
|---|---|---|---|
Size | integer | 1.0 | Required. One more than the highest object number in the file: the number of entries in the full table |
Prev | integer | 1.0 | Only after an incremental update: the offset of the previous cross-reference section |
Root | reference | 1.0 | Required. The document catalog |
Encrypt | dictionary | 1.1 | Only in an encrypted file: the encryption dictionary |
Info | reference | 1.0 | The document information dictionary: title, author, dates |
ID | array | 1.1 | Two byte strings that identify the file; required when it is encrypted |
startxref and %%EOF
The file ends with three lines:
startxref
1668
%%EOF
The number is the byte offset of the x of the last xref
keyword in the file. %%EOF is a comment that marks the end. A line end
after it is common. Some writers add a few bytes after it, and readers look for it
within the last 1,024 bytes rather than at the very end.
How a reader opens a file
- Check the
%PDF-header and read the version. - Find
%%EOFnear the end, then the laststartxrefbefore it, and read the offset. - Go to that offset, which must hold
xref, and read every subsection into a table of object number to offset and generation. - Read the trailer after the table. If it has
Prev, read the older section at that offset too, keeping the entries already read: the newest entry for an object wins. Repeat until a trailer has noPrev. - Take
Rootfrom the newest trailer and read the catalog, then the page tree. IfEncryptis there, set up decryption first. - Read other objects only when they are needed, by looking up their offset.
When the offsets are wrong, as after a file was cut short or edited as text, many
readers rebuild the table by scanning the whole file for n g obj and
the trailer keyword. That repair is what readers do, not something the
format describes.
Incremental updates
A PDF can be changed without rewriting it. The changes go at the end: the new and
changed objects, a new cross-reference section that lists only those objects, and a
new trailer whose Prev points at the previous section. The old bytes
stay as they were.
0Original file header, body, xref, trailer,%%EOFas written…Update 1 changed objects, an xref section of them, a trailer withPrev,%%EOFappended…Update 2 the same again, itsPrevpointing at update 1appended
- A changed object keeps its number and appears again with the new content; the newest copy is the one that counts.
- A deleted object gets a free entry in the new section, with its generation number raised by one, so that a later object can reuse the number with the new generation.
- The new trailer repeats
Root,Size(for the whole file, not just the update), andInfo,EncryptandIDwhere the file has them. The first string ofIDstays the same; the second is usually changed. - The new section can have several subsections, since the changed objects are rarely numbered in one run.
Updates keep the earlier versions in the file, which is how signed documents can be signed more than once (PDF 1.3) and how a viewer can save quickly. A program that saves the whole file again usually drops the old versions.
Line endings
A line ends with a carriage return (0D), a line feed (0A)
or both (0D 0A). Writers on different systems use different ones, and
readers accept all three. The table’s entries are an exception: each ends with
exactly two bytes, a space and a CR or LF, or CR LF, so that every entry is 20
bytes.