Перейти к содержимому
pdftools.kz

Что такое xref

Xref — таблица перекрёстных ссылок: список байтовых смещений, по которому просмотрщик мгновенно находит нужный объект, не читая документ целиком. Программа открывает файл и читает не начало, а конец: там записано ключевое слово startxref и адрес таблицы. Дальше она прыгает по этому адресу, берёт из трейлера ссылку на каталог, из каталога добирается до дерева страниц. Сдвиньте байты — и документ перестанет открываться, хотя внутри цело всё до последнего объекта.

Локально в браузеребез регистрации

Коротко о цифрах

Где записан адрес таблицы
ключевое слово startxref в конце файла
Что хранит запись
смещение объекта в байтах от начала документа
Две реализации
классическая таблица и xref-поток, начиная с PDF 1.5
Успешный код qpdf
3 — предупреждения были, файл собран; 2 — отказ
Метка в отчёте о починке
XREF_REBUILT — таблица построена заново

Путь от последней строки файла до первой страницы

  1. Просмотрщик читает хвост файла и ищет там startxref — последнюю осмысленную запись перед маркером конца.
  2. За ключевым словом стоит число: смещение таблицы в байтах, отсчитанное от самого первого байта документа.
  3. По этому адресу читается таблица — по строке на каждый объект, с его смещением и признаком «занят» или «свободен».
  4. Рядом лежит трейлер со ссылкой на каталог документа, а в каталоге — ссылка на дерево страниц.
  5. Нужная страница достаётся одним переходом по смещению. Именно поэтому документ на тысячу листов открывается так же быстро, как на две.

Две формы одной таблицы

Классическая таблица — обычный текст: заголовок подраздела, а под ним записи фиксированной длины, где смещение дополнено нулями слева. Её видно в любом текстовом редакторе, и именно она стоит в файлах, которые сохранены без сжатия структуры.

Начиная с PDF 1.5 таблицу разрешено хранить как обычный объект-поток, упакованный тем же фильтром, что и содержимое страниц. Это компактнее и позволяет прятать мелкие объекты внутрь общих контейнеров, но глазами такую таблицу уже не прочесть. Встречаются и гибридные файлы, где обе формы лежат рядом ради старых просмотрщиков.

Отчего смещения оказываются неверными

  • Файл правили как текст: заменили одну строку на строку другой длины, и всё, что стоит после неё, уехало.
  • Закачка оборвалась. Конец файла не пришёл, а значит, не пришли ни startxref, ни сама таблица.
  • Два PDF слепили конкатенацией: во втором смещения считаны от его собственного начала, а не от начала общего файла.
  • Инкрементальное сохранение прервалось на середине, и цепочка ссылок на предыдущую таблицу оборвалась.
  • Генератор документа сам записал неверное смещение — редкий, но не экзотический случай у самописных выгрузок.

Что делает восстановление

Починка не пытается исправить сбитые числа. Она читает файл насквозь, отмечает каждое место, где начинается объект, и строит таблицу заново по тому, что нашла. Смещения после этого верны по построению — они получены измерением, а не переписаны из старого файла.

У qpdf, который делает эту работу, код возврата 3 означает «предупреждения были, документ собран», и это успех, а не отказ. Настоящая ошибка — код 2: она приходит, когда сплошной просмотр не нашёл ни трейлера, ни связного графа объектов. В отчёте о починке перестроенная таблица помечается как XREF_REBUILT, и это самая частая находка из всех.

Частые вопросы

Можно ли починить xref вручную в текстовом редакторе?

Теоретически да, практически нет. Любая правка сдвигает все последующие смещения, поэтому пересчитывать придётся всю таблицу целиком, а не одну строку. Сплошной просмотр файла делает то же самое за один проход и без арифметики.

Что означает сообщение «can't find startxref»?

Программа дочитала до конца файла и не нашла там указателя на таблицу. Чаще всего это оборванная закачка или обрезанный при копировании файл, реже — мусор, дописанный в хвост почтовым шлюзом или архиватором.

Влияет ли таблица на вес документа?

Заметно только на мелких файлах. Каждая запись занимает два десятка байт, поэтому у документа с сотней объектов таблица весит около двух килобайт, а у сотни страниц с картинками она теряется на фоне самих изображений.

Почему после восстановления файл изменился в размере?

Документ записан заново: объекты уложены подряд, старые версии страниц из инкрементальных сохранений выброшены, таблица построена с нуля. Файл может стать и меньше исходного, и немного больше, если структура была упакована сильнее.

Рядом