【问题标题】:problems with calculating byte offset计算字节偏移量的问题
【发布时间】:2014-12-28 14:19:32
【问题描述】:

我现在正在努力理解 PDF 敲击,但我在计算字符串的字节偏移量时遇到了一点问题。对象的偏移量是从文件开头到对象的索引(6 0 obj)计算出来的。

我有一个可用的 hello world PDF 文件,但是当我计算偏移量时,我得到的偏移量与外部参照表中的不同。

如果有人知道这是如何计算的,请告诉我!

例子:

0 6 obj xref:9 me:17

0 1 obj xref:60 me:72

0 4 obj xref:145 me 187

(我用 "\r\n" (2) 作为换行符)

Adobe 标准:http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/pdf_reference_archives/PDFReference.pdf

%PDF-1.4
%%EOF
6 0 obj
<<
/Type /Catalog
/Pages 5 0 R
>>
endobj
1 0 obj
<<
/Type /Page
/Parent 5 0 R
/MediaBox [ 0 0 612 792 ]
/Resources 3 0 R
/Contents 2 0 R
>>
endobj
4 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont/Helvetica
>>
endobj
2 0 obj
<<
/Length 53
>>
stream
BT
/F1 24 Tf
1 0 0 1 260 600 Tm
(Hello World)Tj
ET
endstream
endobj
5 0 obj
<<
/Type /Pages
/Kids [ 1 0 R ]
/Count 1
>>
endobj
3 0 obj
<<
/ProcSet[/PDF/Text]
/Font <</F1 4 0 R >>
>>
endobj
xref
0 7
0000000000 65535 f
0000000060 00000 n
0000000228 00000 n
0000000424 00000 n
0000000145 00000 n
0000000333 00000 n
0000000009 00000 n
trailer
<<
/Size 7
/Root 6 0 R
>>
startxref
488
%%EOF

【问题讨论】:

    标签: pdf pdf-generation adobe offset postscript


    【解决方案1】:

    这是一个非常有趣的文件,最初阅读 PDF 规范让我更加困惑 :-)。在这种情况下(我会让一些人生气)我会简单地保存示例 PDF 文件并按照@KenS 在他之前的回答中建议的那样做;在 Acrobat 中打开它,如果 Acrobat 报告它已损坏或在您关闭文件时要求您保存 - 它不喜欢它,您可以假设您弄错了。

    这个文件有趣的原因是第二行:

    %%EOF
    

    我不同意 KenS 的观点,即让这一行自动使文件无效 - 我在 ISO 32000 中找不到说明这一点的文本。文本说文件末尾的 %%EOF 行 具有语法意义(并解释了它为什么存在),并且它指出任何以百分比字符 (%) 开头的行都是 评论以及这意味着什么。但是它没有任何地方声明 %%EOF 不允许作为文件中其他位置的注释(尽管我认为这是一件愚蠢的事情,但这是不同的)。

    如果 %%EOF 行不存在,则外部参照表是正确的。如果它在那里,那就错了。对我在文档中阅读的内容的更多解释:

    1) 据我所知,偏移量是从文件的第一个字节开始的(它是字节偏移量,而不是字符偏移量),它是“0”,然后向上计数。这背后的想法是您可以打开一个文件,将文件读取位置设置为给定的偏移量并开始读取。因此,如果您在显示实际字节的二进制编辑器中打开文件,偏移量应该与您在那里看到的相匹配。如果您的 %%EOF 行不存在,则意味着第一个对象(6 0 obj)实际上从偏移量 9 开始(如果您的行尾字符是单字节行尾)。此时它与 PDF 规范本身中给出的示例相匹配,因此我确信如果第二行 (%%EOF) 不在 PDF 文件中,偏移量 9 是正确的。

    2) 第二行以百分号开头,使其成为注释。 PDF 规范规定注释(从 % 符号到但不包括行尾字符的所有内容)应被解释为单个空白字符。这很有趣,可能会导致各种猜测,这对跟随它的对象的偏移意味着什么,但坦率地说,由于我之前所说的,所有这些猜测都是无序且无关紧要的。

    这背后的想法是,您可以打开一个文件,将文件读取位置设置为给定的偏移量并开始读取。

    这正是交叉引用表的用途,应该按字面意思理解。换句话说,假设单字节行结束字符,示例文件中的对象 6 从偏移量 15 开始,这应该是该对象的 XREF 表中的数字。

    再次,考虑@KenS 的评论,你不能只假设行尾是两个字节,你必须知道它们是什么(它们可能是混合所以你甚至不能假设所有行都相同)。如果此文件的所有行都有两个字节的行结尾,那么您的计数 17 将是正确的。

    【讨论】:

      【解决方案2】:

      你不能假设一个行尾是一对\r\n,它可能是\r、\n或\r\n,你需要使用二进制编辑器来确定。如果不访问原始文件,我们也无法告诉您哪个值是正确的,上面的剪切/粘贴根本不够好,抱歉。虽然 9 不可能是正确的除非 %%EOF 是虚假的......

      您引用的 PDF 文件无论如何都不正确,您不应该将 %%EOF 作为第二行,它“应该”是二进制字节序列,高位设置以确保 PDF 文件作为二进制传输文件。

      您如何知道 PDF 文件中的外部参照是正确的?如果您使用 Acrobat 打开它,它是否会在退出时保存更改?这肯定表明 Acrobat 为您重建了外部参照,因为它不正确.....

      [为清楚起见而编辑,因为对于 cmets 来说太长了]

      我的解释应该更清楚。我在最初的回答中将 2 个陈述压缩为 1 个,并打算在 cmets 中对其进行澄清。该文件不正确,外部参照偏移在我看来是错误的,并且在初始检查时 %%EOF 似乎是错误的(但请参见下文),这在某种程度上看起来像是伪造的(通过剪切/粘贴插入,或由编辑,或其他)。

      从技术上讲,您可以在 PDF 文件的任何位置(但在字符串和流之外)中包含任何以 % 开头的文本,前提是您正确地考虑了它并且不破坏 PDF 语法。但是我仍然不会在一个 PDF 文件中放置两个 %%EOF cmets,这太容易让头脑简单的 PDF 消费者感到困惑。

      我认为在'x y obj' 语句之前添加评论不一定是错误的(我不会这样做,但这不是一回事)。这也不能完全否定 David 关于以下内容的观点:

      The idea behind this is that you can open a file, set the file read position to a given offset and start reading.
      

      前提是 PDF 使用者准备阅读评论并且不期望有空格或 'x y obj' 语句(并且我已经在此处看到了前面有空格的 PDF 文件)。这是有争议的,虽然我会阅读规范说外部参照偏移应该精确指向'x y obj'行的第一个字节,但实际上并没有这么多话在规范中。 PDF 使用者确实需要能够在对象定义过程中处理 cmets。例如我认为:

      1 0 obj
      %% Here's a comment
      <<
      /Type /Page
      /Parent 5 0 R
      /MediaBox [ 0 0 612 792 ]
      /Resources 3 0 R
      /Contents 2 0 R
      >>
      

      是合法的。该行以 '%' 开头,它不在字符串或流上下文中,并且不会破坏 PDF 语法,消费者应该直接跳过它。

      这与以下非常没有太大不同:

      %% Here's a comment
      1 0 obj
      <<
      /Type /Page
      /Parent 5 0 R
      /MediaBox [ 0 0 612 792 ]
      /Resources 3 0 R
      /Contents 2 0 R
      >>
      

      同样,我自己不会这样做(或者如果我这样做了,我会将外部参照指向 1 0 obj 的开头,但我认为这样可以争论。

      但在原始示例中,我的二进制编辑器说(以 2 字节行结尾)对象 4 从偏移量 187 开始,如果我使用 1 字节结尾,则下降到 170。为了使对象的外部参照正确,我假设行尾是 1 个字节,我删除了“%%EOF\n”。但是从 170 中减去 6 个字节仍然是 164,因此与外部参照所包含的 145 相去甚远。如果不删除真正的 PDF 运算符/结构,我看不到任何方法可以让对象 4 位于位置 145。

      【讨论】:

      • PDF 文件不正确 - 您给出的原因使该文件看起来可疑但尚未不正确。
      • PDF 文件的最后一行应该是 %%EOF,实际上不应该是 2。尽管(像往常一样)Acrobat 可以容忍这种事情。
      • 该文件肯定不正确。外部参照表示对象 6 0 位于偏移量 9 处,这是 %%EOF 的开头,而不是“6 0 obj”行。我想你可能会争辩说,由于 cmets 被忽略,这是合法的,但它相当头发分裂。规范说外部参照偏移应该指向“对象的开始”。这是使外部参照正确的一种方法,如果 Acrobat 忽略了如此细微的区别,我一点也不感到惊讶。但是没有办法让 1 0 obj 小于 64 字节(甚至计算 1 字节换行符),并且外部参照说 60。
      • 我认为,如果您从第二行删除 %%EOF,并且计数 1 个字节的行会中断外部参照对于对象 6 和 1 的正确工作,因此第二行看起来完全错误。对象 4 的偏移量看起来都错了
      • 如我的回答中所述,我并不真正同意您关于此 %%EOF 使文件无效这一事实的说法;我找不到任何强有力的语言来证明这种情况。但我同意你的其他观点和你在这里所做的计算。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-13
      • 1970-01-01
      • 2012-10-24
      • 1970-01-01
      • 2013-08-24
      • 2011-11-16
      相关资源
      最近更新 更多