我正在尝试使用PDF Clown库来运行 Stefano Chizzolini (真棒人:PDFClown的创建者)编写的解析PDF 的Java代码。我收到了这个错误,我不知道我能做些什么来解决这个问题。
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中的this symbol。
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();
}
}
答案 0 :(得分: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 Reference Manual 中的 TrueType字体文件:第6章中的概述
org.pdfclown.documents.contents.fonts.OpenFontParser
中的TrueType字体文件 >
另一方面,有许多PDF生成器将嵌入的TrueType字体缩减为PDF查看器(最重要的Adobe Reader)所需的基本要素,而name
表似乎并不严格必需的。
此外,表格name
仅用于PDFClown中的一个目的,以确定相关字体的名称,即使字体名称可以从 BaseFont 条目确定相关的字体字典也是。实际上后面的条目是PDF规范的必需,而name
表中的 PostScript名称条目是可选到TTF手册。
因此,使用PDF字体字典中的 BaseFont 条目可以更好地替代此name
表格访问。
我能做些什么来解决这个问题吗?
您可以通过向相关嵌入式TTF添加name
表来修复不完全有效的PDF,也可以修补PDFClown以忽略丢失的丢失表:在课程sample file中编辑方法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在他现在删除的答案中提供的{{3}}给出了开始分析的更多动力。