为什么尾部对象报告 "Size" 条目的先前值?
Why does the trailer object report a previous value for the "Size" entry?
我正在尝试编写代码来调查签名后对 PDF 文档的更改(欢迎指点)并遇到了这个奇怪的问题。
我想检索在 xref
表中索引的 PDF 文件中的对象数。看起来,虽然预告片字典中的所有其他条目都是最终预告片的条目,但 Size
的数字是原始预告片中的数字。在我的特殊情况下,对原始文档进行了 2 次更新(添加了 2 个外部参照表,总共 3 个),从原始文档 550 添加了最多 567 个对象。
这就是我从预告片字典中获取 Size
的方式:
private static long getMaxObjId(PDDocument doc) {
COSDocument cosdoc = doc.getDocument();
COSDictionary trailer = cosdoc.getTrailer();
long maxobj = trailer.getLong(COSName.SIZE);
return maxobj;
}
我正在使用 PDFBox 2.0.21。
你是对的。 Size trailer 中的条目包含最低的(即通常是 oldest) Size 文档中所有预告片的值,而 trailer 中的所有其他条目包含其各自键的最新值。
造成这种情况的原因比我原先想象的还要糟糕:您获得的 trailer 对象不仅仅是最新的(或者,考虑到 Size value, the earliest) trailer 字典中的字典,它是所有 trailer 字典的并集,从最早的trailer开始Prev 链接到最新的。
到目前为止一切顺利。但这不应该意味着该联合预告片中的所有条目都应该具有来自最新 trailer 字典的值和条目键吗?在看到用于创建联合的 COSDictionary.addAll(COSDictionary)
代码之前,我就是这么想的:
/**
* This will add all of the dictionaries keys/values to this dictionary.
* Only called when adding keys to a trailer that already exists.
*
* @param dic The dictionaries to get the keys from.
*/
public void addAll(COSDictionary dic)
{
dic.forEach((key, value) ->
{
/*
* If we're at a second trailer, we have a linearized pdf file, meaning that the first Size entry represents
* all of the objects so we don't need to grab the second.
*/
if (!COSName.SIZE.equals(key) || !items.containsKey(COSName.SIZE))
{
setItem(key, value);
}
});
}
此处明确不替换现有的 Size 条目!
这解释了最初的观察结果,即 Size 条目在 预告片 中包含最低的(即通常是 oldest) Size 文档中所有尾部的值,而那个 尾部中的所有其他条目 包含最新值他们各自的钥匙。
这些评论产生了这样一种假设,即这是 PDFBox 默认从前面解析 PDF、忽略交叉引用表以及唯一相关的测试 PDF 没有正常增量更新的时代的遗物,仅仅完全没有更新的和线性化的,线性化使用为逆序增量更新定义的机制。并且仅在此类线性化文档的情况下,此异常才有意义。
但为什么我认为这比最初认为的更糟糕:这个 addAll
方法是一个 public COSDictionary
方法,其名称与 Java 集合框架 addAll
。因此,它使用户认为第一个 JavaDoc 行 This will add all of the dictionaries keys/values to this dictionary
是正确的;所以他会用它来完成那个任务,从没想过 Size 条目不会被替换。
事实上,即使在 PDFBox 代码本身中,COSDictionary.addAll(COSDictionary)
也用于除预告片联合之外的其他上下文,尽管有第二行 JavaDoc,Only called when adding keys to a trailer that already exists.
应该检查并修复此问题。为此,我创建了一个 Jira 问题,PDFBOX-4999。
我正在尝试编写代码来调查签名后对 PDF 文档的更改(欢迎指点)并遇到了这个奇怪的问题。
我想检索在 xref
表中索引的 PDF 文件中的对象数。看起来,虽然预告片字典中的所有其他条目都是最终预告片的条目,但 Size
的数字是原始预告片中的数字。在我的特殊情况下,对原始文档进行了 2 次更新(添加了 2 个外部参照表,总共 3 个),从原始文档 550 添加了最多 567 个对象。
这就是我从预告片字典中获取 Size
的方式:
private static long getMaxObjId(PDDocument doc) {
COSDocument cosdoc = doc.getDocument();
COSDictionary trailer = cosdoc.getTrailer();
long maxobj = trailer.getLong(COSName.SIZE);
return maxobj;
}
我正在使用 PDFBox 2.0.21。
你是对的。 Size trailer 中的条目包含最低的(即通常是 oldest) Size 文档中所有预告片的值,而 trailer 中的所有其他条目包含其各自键的最新值。
造成这种情况的原因比我原先想象的还要糟糕:您获得的 trailer 对象不仅仅是最新的(或者,考虑到 Size value, the earliest) trailer 字典中的字典,它是所有 trailer 字典的并集,从最早的trailer开始Prev 链接到最新的。
到目前为止一切顺利。但这不应该意味着该联合预告片中的所有条目都应该具有来自最新 trailer 字典的值和条目键吗?在看到用于创建联合的 COSDictionary.addAll(COSDictionary)
代码之前,我就是这么想的:
/**
* This will add all of the dictionaries keys/values to this dictionary.
* Only called when adding keys to a trailer that already exists.
*
* @param dic The dictionaries to get the keys from.
*/
public void addAll(COSDictionary dic)
{
dic.forEach((key, value) ->
{
/*
* If we're at a second trailer, we have a linearized pdf file, meaning that the first Size entry represents
* all of the objects so we don't need to grab the second.
*/
if (!COSName.SIZE.equals(key) || !items.containsKey(COSName.SIZE))
{
setItem(key, value);
}
});
}
此处明确不替换现有的 Size 条目!
这解释了最初的观察结果,即 Size 条目在 预告片 中包含最低的(即通常是 oldest) Size 文档中所有尾部的值,而那个 尾部中的所有其他条目 包含最新值他们各自的钥匙。
这些评论产生了这样一种假设,即这是 PDFBox 默认从前面解析 PDF、忽略交叉引用表以及唯一相关的测试 PDF 没有正常增量更新的时代的遗物,仅仅完全没有更新的和线性化的,线性化使用为逆序增量更新定义的机制。并且仅在此类线性化文档的情况下,此异常才有意义。
但为什么我认为这比最初认为的更糟糕:这个 addAll
方法是一个 public COSDictionary
方法,其名称与 Java 集合框架 addAll
。因此,它使用户认为第一个 JavaDoc 行 This will add all of the dictionaries keys/values to this dictionary
是正确的;所以他会用它来完成那个任务,从没想过 Size 条目不会被替换。
事实上,即使在 PDFBox 代码本身中,COSDictionary.addAll(COSDictionary)
也用于除预告片联合之外的其他上下文,尽管有第二行 JavaDoc,Only called when adding keys to a trailer that already exists.
应该检查并修复此问题。为此,我创建了一个 Jira 问题,PDFBOX-4999。