计算字节偏移的问题

时间:2014-12-28 14:19:33

标签: pdf pdf-generation adobe offset postscript

我现在正在理解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)作为换行符)

Adob​​e Standart: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

2 个答案:

答案 0 :(得分:1)

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

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

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

[为了清晰而编辑,因为评论时间过长]

我的解释应该更清楚。我在最初的答案中将2个陈述归为1,并打算在评论中澄清。该文件不正确,外观参照偏移在我看来是错误的,并且在初始检查时看起来是错误的%% EOF(但见后面),看起来它在某种程度上是假的(通过剪切/粘贴插入,或者由编辑或其他东西)。

从技术上讲,你可以在PDF文件中的任何地方(但在字符串和流之外)开始任何文本,只要你正确地考虑它并且不破坏PDF语法。但我仍然不会在PDF文件中添加两个%% EOF注释,它太可能会混淆简单的PDF用户。

我认为在'x y obj'声明之前发表评论并不一定是错的(我不会这样做,但这不是一回事)。它也没有完全无效大卫的观点:

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文件)。这是有争议的,虽然我会阅读规范说xref偏移应该指向'x y obj'行的第一个字节,它实际上并没有这么说规范中有很多单词。 PDF用户确实需要能够在对象定义本身的过程中处理注释。例如我认为:

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
>>

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

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

答案 1 :(得分:1)

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

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

%%EOF

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

如果%% EOF行没有,则XREF表是正确的。如果它存在,那就错了。我在文档中读到的更多解释:

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

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

  

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

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

再次,请@ KenS&#39;考虑到注释,你不能只假设行结尾是两个字节,你必须知道它们是什么(它们可能是混合所以你甚至不能假设所有行都相同) 。如果此文件对于所有行都有两个字节行结尾,则计数为17将是正确的。