3

我正在尝试运行由Stefano Chizzolini(真棒家伙:PDFClown 的创建者)编写的 Java 代码,以使用 PDF Clown 库解析 PDF 。我收到了这个错误,我不知道我能做些什么来解决这个问题。

Exception in thread "main" org.pdfclown.util.parsers.ParseException: 'name' table does NOT exist.
at org.pdfclown.documents.contents.fonts.OpenFontParser.getName(OpenFontParser.java:570)
at org.pdfclown.documents.contents.fonts.OpenFontParser.load(OpenFontParser.java:221)
at org.pdfclown.documents.contents.fonts.OpenFontParser.<init>(OpenFontParser.java:205)
at org.pdfclown.documents.contents.fonts.TrueTypeFont.loadEncoding(TrueTypeFont.java:91)
at org.pdfclown.documents.contents.fonts.SimpleFont.onLoad(SimpleFont.java:118)
at org.pdfclown.documents.contents.fonts.Font.load(Font.java:738)
at org.pdfclown.documents.contents.fonts.Font.<init>(Font.java:351)
at org.pdfclown.documents.contents.fonts.SimpleFont.<init>(SimpleFont.java:62)
at org.pdfclown.documents.contents.fonts.TrueTypeFont.<init>(TrueTypeFont.java:68)
at org.pdfclown.documents.contents.fonts.Font.wrap(Font.java:253)
at org.pdfclown.documents.contents.FontResources.wrap(FontResources.java:72)
at org.pdfclown.documents.contents.FontResources.wrap(FontResources.java:1)
at org.pdfclown.documents.contents.ResourceItems.get(ResourceItems.java:119)
at org.pdfclown.documents.contents.objects.SetFont.getResource(SetFont.java:119)
at org.pdfclown.documents.contents.objects.SetFont.getFont(SetFont.java:83)
at org.pdfclown.documents.contents.objects.SetFont.scan(SetFont.java:97)
at org.pdfclown.documents.contents.ContentScanner.moveNext(ContentScanner.java:1330)
at org.pdfclown.tools.TextExtractor.extract(TextExtractor.java:626)
at org.pdfclown.tools.TextExtractor.extract(TextExtractor.java:296)
at PDFReader.FullExtract.run(FullExtract.java:71)
at PDFReader.FullExtract.main(FullExtract.java:142)

我知道库包中的类OpenFontParser抛出了这个错误。我能做些什么来解决这个问题吗?

此代码适用于大多数 PDF。我有一个无法解析的 PDF。我猜这是因为pdf下面的这个符号。

public class PDFReader extends Sample {

@Override
public void run()
{
    String filePath = new String("C:\\Users\\XYZ\\Desktop\\SomeSamplePDF.pdf");

    // 1. Open the PDF file!
    File file;
    try
    {file = new File(filePath);}
    catch(Exception e)
    {throw new RuntimeException(filePath + " file access error.",e);}

    // 2. Get the PDF document!
    Document document = file.getDocument();

    // 3. Extracting text from the document pages...
    for(Page page : document.getPages())
    {
    extract(new ContentScanner(page)); // Wraps the page contents into a scanner.

    }
    close(file);
}

private void close(File file) {
    // TODO Auto-generated method stub

}

/**
Scans a content level looking for text.
 */
/*
NOTE: Page contents are represented by a sequence of content objects,
possibly nested into multiple levels.
 */
private void extract(
        ContentScanner level
        )
{
    if(level == null)
        return;

    while(level.moveNext())
    {
        ContentObject content = level.getCurrent();
        if(content instanceof ShowText)
        {
            Font font = level.getState().getFont();
            // Extract the current text chunk, decoding it!
            System.out.println(font.decode(((ShowText)content).getText()));
        }
        else if(content instanceof Text
                || content instanceof ContainerObject)
        {
            // Scan the inner level!
            extract(level.getChildLevel());
        }
    }
}

private boolean prompt(Page page)
{
    int pageIndex = page.getIndex();
    if(pageIndex > 0)
    {
        Map<String,String> options = new HashMap<String,String>();
        options.put("", "Scan next page");
        options.put("Q", "End scanning");
        if(!promptChoice(options).equals(""))
            return false;
    }

    System.out.println("\nScanning page " + (pageIndex+1) + "...\n");
    return true;
}

public static void main(String args[])
{
    new PDFReader().run();
    }

}
4

1 回答 1

2

问题

正如堆栈跟踪所示,问题在于 PDF 中嵌入的某些 TrueType 字体不包含name表格,即使它是必需的表格:

org.pdfclown.util.parsers.ParseException: 'name' table does NOT exist.
...
at org.pdfclown.documents.contents.fonts.TrueTypeFont.loadEncoding(TrueTypeFont.java:91)

因此,严格来说,嵌入的字体是无效的,因此嵌入的 PDF 也是如此。由于这个有效性问题,PDFClown 遇到了异常。

一些背景

TrueType 字体文件由一系列连接的表格组成。...

第一个表是字体目录,一个特殊的表,便于访问字体中的其他表。该目录后面是一系列包含字体数据的表格。这些表格可以按任何顺序出现。所有字体都需要某些表格。其他是可选的,具体取决于特定字体的预期功能。

所需的表格必须出现在任何有效的 TrueType 字体文件中。所需表及其标签名称如表 2 所示。

表 2:所需表

Tag     Table 
'cmap'  character to glyph mapping 
'glyf'  glyph data 
'head'  font header 
'hhea'  horizontal header 
'hmtx'  horizontal metrics 
'loca'  index to location 
'maxp'  maximum profile 
'name'  naming 
'post'  PostScript 

(部分TrueType 字体文件: TrueType 参考手册中的第 6 章The TrueType 字体文件的概述

但是,另一方面,有许多 PDF 生成器将嵌入的 TrueType 字体缩减为 PDF 查看器(最重要的是 Adob​​e Reader)所需的基本要素,而且该name表格似乎并不是严格要求的。

此外,该表name在 PDFClown 中仅用于一个目的,即确定所讨论字体的名称,即使字体名称也可以从相关字体字典的BaseFont条目中确定。实际上,PDF 规范需要后一个条目,而根据 TTF 手册,表中字体条目的PostScript 名称是可选的。name

因此,使用 PDF 字体字典中的BaseFont条目将是此name表访问的更好替代方法。

修复它

我能做些什么来解决这个问题吗?

您可以通过将name表格添加到有问题的嵌入式 TTF 来修复不完全有效的 PDF,或者您可以修补 PDFClown 以忽略丢失的丢失表格:在类中org.pdfclown.documents.contents.fonts.OpenFontParser编辑方法getName

private String getName(
  int id
  ) throws EOFException, UnsupportedEncodingException
{
  // Naming Table ('name' table).
  Integer tableOffset = tableOffsets.get("name");
  if(tableOffset == null)
    throw new ParseException("'name' table does NOT exist.");

将其替换throw new ParseException("'name' table does NOT exist.")return null

附言

虽然可以仅使用 OP 提供的信息来分析问题,但@akarshad在他现在已删除的答案中提供的示例文件提供了更多开始分析的动力。

于 2014-05-22T10:32:12.100 回答