0

I opened a pdf in a regular text editor, changed one line of text and then saved it again. It would appear that this caused certain metadata to be corrupted, and i can't figure out how i can get it back. I can still open it in the text editor but opening it as pdf just shows empty pages.

Is there any way to repair this file?

3
  • Why didnt you just change the line of text while the pdf was open or is it protected and read only? Feb 26, 2016 at 6:38
  • 1
    PDF files are a list of objects and after the objects there is an xref table that has pointers to each object from start of file. You could edit text and keep exactly the same amount of characters without updating pointers. Or, if you change/add/remove text then you must update every xref pointer in table after the text that you added as well as updating startxref pointer. It's a bit tricky especially for big files but it is do-able.
    – gaoithe
    Feb 6 at 19:58
  • 1
    it isn't doable with a text editor. It is doable with a hex editor
    – Yorik
    Feb 6 at 20:36

3 Answers 3

5

Go home and write one hundred times "PDF is not a text format, and must never, ever be edited with a text editor or word processor!"

PDF is a complex object-based document format, which relies on a "table of contents" (aka xref table), which points to the exact position within the file. When you change something in a text editor, you will most likely shift everything after the edit, and therefore make the xref table pointing at the wrong places.

A well-behaving PDF viewer tries to repair such things, but quickly runs into its limitations.

Also, it is very likely that your text editor also messed up binary blocks, where by coincidence a byte corresponds to one of the line ending characters. … and you have successfully corrupted the PDF beyond all repair…

So, the suggestion to go to a backup version is the best advice about your file.

1

You could do this

Go to the folder that used to contain the file or folder, right-click it, and then click restore previous versions.

You'll see a list of available previous versions of the file or folder. The list will include files saved on a backup

Select one of the one you want and you will be fine.

Next time if you are going to edit the Metadata or something like that, always create a backup copy

0

PDF files are a list of objects and after the objects there is an xref table that has pointers to each object from start of file. You could edit text and keep exactly the same amount of characters without updating pointers. Or, if you change/add/remove text then you must update every xref pointer in table after the text that you added as well as updating startxref pointer. It's a bit tricky especially for big files but it is do-able.

See the below example .pdf xref table, values are decimal. The first object is 58 bytes into file, the next is 346, etc ..

xref
0 5
0000000000 65535 f
0000000058 00000 n
0000000346 00000 n
0000000558 00000 n
0000000705 00000 n
0000000782 00000 n

See also the startxref pointer must be updated, the "xref" start of xref table is at 1193 bytes from start of file.

startxref
1193

Please forgive me if I have pointer errors in here! Thanks @K J for pointing them out, I have, I think, corrected them below for uniz. And see further below for xref table and startxref pointer value that should work with this example if windows/dos line endings are used.

Example file - tested this copies ok into local file and parses as PDF. Tested DUH with evince which is great but which actually fixes a broken xref table and ignores size errors. Clever. But not a good test on my part. Apologies!

If you change anything below startxref you don't have to update any pointers.

Anything above and you have to adjust the pointers.

%PDF-1.6

% First object defines a stream with red square
1 0 obj
<<
    /Length 54
>>
stream
1 0 0 RG
5 w
100 100 m
200 100 l
200 200 l
100 200 l
s
endstream
endobj

% The second object. Page containing object 1 red square.
% The "R" means "Reference", and `1 0 R` is saying "look at object number 1 0
% It also points to a "Pages" object `3 0 R`.
2 0 obj
<<
    /Type /Page
    /Parent 3 0 R
    /MediaBox [0 0 320 500]
    /Contents [1 0 R]               
>>
endobj

% The third object. "Pages" object. The `2 0 R` is reference to the "Page" object. 1 page in this doc.
3 0 obj
<<
    /Type /Pages
    /Kids [2 0 R ]
    /Count 1
>>
endobj

% The fourth object. A "Catalog" object that provides the main structure of the PDF.
4 0 obj
<<
    /Type /Catalog
    /Pages 3 0 R
>>
endobj

% A fifth object - title
5 0 obj
<<
    /Title (Test PDF Title)
    /Producer (James hand edit emacs FTW)
>>
endobj

% The xref table. Lookup table, lists all the objects with pointer from start of file (emacs count-words-region helps fix up).
% (defun wh/byte-offset-at-point () "Report the byte offset (0-indexed) in the file corresponding to the position of point." (interactive) (message "byte offset: %d" (1- (position-bytes (point)))))
xref
0 5
0000000000 65535 f
0000000058 00000 n
0000000349 00000 n
0000000573 00000 n
0000000729 00000 n
0000000812 00000 n

% The trailer contains some metadata about the PDF.
%   - There are 4 entries in the `xref` table.
%   - The root of the document is object 4 (the "Catalog" object)
trailer
<<
    /Size 5
    /Root 4 0 R
    /Info 5 0 R
>>

% The startxref marker tells us that we can find the xref table ? bytes after the start of the file.
startxref
1229

% WE can add any comments below here without need to adjust pointers. 
% From https://alexwlchan.net/2024/big-pdf/?utm_source=tldrnewsletter
% "it got very fiddly to redo all the lookup tables!"
% https://help.callassoftware.com/a/798383-how-to-create-a-simple-pdf-file
% https://superuser.com/questions/300405/is-it-possible-to-edit-a-pdf-file-directly
% https://www.oreilly.com/library/view/pdf-explained/9781449321581/ch04.html
% https://superuser.com/questions/1045351/pdf-corrupt-after-opening-and-saving-in-raw-text

% The end-of-file marker.
%%EOF

Note that if you copy this into windows/dos editor that uses dos style line endings you will have to ADJUST pointers so the xref table becomes like this:

xref
0 5
0000000000 65535 f
0000000061 00000 n
0000000370 00000 n
0000000604 00000 n
0000000769 00000 n
0000000860 00000 n

And the startxref pointer becomes like this:

startxref
1286

Credit to this for example: https://alexwlchan.net/2024/big-pdf/?utm_source=tldrnewsletter "it got very fiddly to redo all the lookup tables!"

And he got it from here: https://help.callassoftware.com/a/798383-how-to-create-a-simple-pdf-file

Useful reference: https://www.oreilly.com/library/view/pdf-explained/9781449321581/ch04.html

2
  • 1
    Use of a text editor will thrash embedded binary data. PDFs contain arbitrary data and can embed literally anything including executable files.
    – Yorik
    Feb 6 at 20:38
  • Good point. PDFs are agnostic with regards to line endings but, yeah if you paste into windows text editor and 2 char CRLF is now line ending then need to adjust all pointers by that. Oh nuts Evince PDF viewer on linux seems to ignore pointer errors actually, hence my testing of the document was not a good test, sorry, interesting good spot with the "/Size 4". Thanks for pointing these out.
    – gaoithe
    Feb 7 at 9:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .