为什么应用程序应该反向读取 PDF 文件?

Why should applications read a PDF file backwards?

我正在努力思考 PDF 文件结构。有一个 header、一个 body 和 objects、一个 cross-reference table 和一个预告片。在 Adob​​e 的官方 PDF reference 中,关于文件预告片的第 3.4.4 节,我们可以看到:

The trailer of a PDF file enables an application reading the file to quickly find the cross-reference table and certain special objects. Applications should read a PDF file from its end.

我觉得这看起来效率很低。在加载整个文件之前,我无法以这种方式向用户显示任何内容(甚至第一页也不行)。好吧,准确地说,我可以——如果我的文件是线性化。但这是可选的,意味着在写入和读取此类文件时会有一些额外的开销。

而不是整个线性化的东西,将引用 放在 和 body 前面会更容易(后面是页面上的 objects 1、第 2 页、第 3 页……)。但是 Adob​​e 的人可能有他们的理由将它放在 之后。我只是没有看到他们。所以...

为什么 cross-reference table 放在 之后 body?

PDF 是在硬盘驱动器写入文件速度很慢的时候发明的……真的是 s-l-o-w。通过将外部参照放在末尾,您可以通过简单地将新对象和更新的外部参照附加到文件末尾而不是重写整个文件来快速更改文件。

不仅驱动器速度慢(引起了@joelgeraci 的回答中的争论),而且典型计算机中可用的 RAM 也少得多。因此,在创建 pdf 时,必须尽早将数据写入文件,这比人们知道文件有多大或交叉引用会变得有多大要早得多。因此,在最后写交叉引用是很自然的结果。

我同意已经提到的两个原因,但不是因为硬件限制 "back in the day",而是规模。人们很容易认为可以用不同的方式更好地处理包含几页文本的发票,但是一本书或包含 1,000 张照片的 PDF 呢?

尾部有预告片,您可以在处理文件时将 images/text/fonts 写入文件,然后将它们从内存中丢弃,同时简单地存储要用于写入预告片的每个对象的文件偏移量。

如果预告片必须先出现,那么您将不得不读取(或者甚至在嵌入字体的情况下生成)所有这些对象以获得它们的大小,以便您可以写出预告片,然后写下所有文件的对象。因此,您要么读取、调整大小、丢弃,然后再次读取,要么尝试将所有内容保存在 ram 中,直到您可以将它们写入文件。

当我们在共享硬件上的 VM 上的 docker 容器中 运行 时,写入速度和内存仍然是我们今天要解决的问题..