当前位置:职场发展 > PDFBOX详细说明

PDFBOX详细说明

  • 发布:2023-10-09 21:13

PDFBOX详细说明

总结

  自 1993 年 Adob​​e 首次发布公共 PDF 参考以来,支持各种语言和平台的 PDF 工具和库如雨后春笋般涌现。但Adobe技术在Java应用开发方面的支持相对滞后。
  自 1993 年 Adob​​e 首次发布公共 PDF 参考以来,支持各种语言和平台的 PDF 工具和库如雨后春笋般涌现。但Adobe技术在Java应用开发方面的支持相对滞后。这是一个奇怪的现象,因为PDF文档是企业信息系统存储和交换信息的大势所趋,而Java技术特别适合这种应用。然而,Java 开发人员似乎直到最近才拥有成熟且可用的 PDF 支持。
  PDFBox(BSD许可下的开源项目)是一个纯Java类库,供开发人员阅读和创建PDF文档。它具有以下功能:

  • 提取文本,包括 Unicode 字符。
  • 与Jakarta Lucene等文本搜索引擎的集成过程非常简单。
  • 加密/解密PDF文档。
  • 从 PDF 和 XFDF 格式导入或导出表单数据。
  • 将内容附加到现有 PDF 文档。
  • 将 PDF 文档剪切为多个文档。
  • 覆盖 PDF 文档。

  

PDFBox API

  PDFBox 的设计采用面向对象的方法来描述 PDF 文档。 PDF文档的数据是基本对象的集合:数组、布尔类型、字典、数字、字符串和二进制流。 PDFBox 在 org.pdfbox.cos 包(COS 模型)中定义了这些基本对象类型。您可以使用这些对象以任何方式与 PDF 文档进行交互,但您应该首先对 PDF 文档的内部结构和高级概念有一些深入的了解。例如,页面和字体是具有特殊属性的字典对象; PDF参考手册提供了这些特殊属性的含义和类型的解释,但这是一个繁琐的文档审查过程。
  于是,org.pdfbox.pdfmodel包(PD模型)应运而生。它基于 COS 模型,但提供了高级 API 来以熟悉的方式访问 PDF 文档对象(图 1)。封装底层 COS 模型的 PDPage、PDFont 等类都在这个包中。

  请注意,尽管 PD 模型提供了一些出色的功能,但它仍然是一个正在开发的模型。在某些情况下,您可能需要 COS 模型的帮助才能访问 PDF 的特定功能。所有 PD 模型对象都提供返回相应 COS 模型对象的方法。所以,一般情况下,你都会使用PD模型,但是PD模型并不是只要你可以直接操作底层的COS模型即可。
  上面已经对PDFBox进行了大概的介绍。现在是时候举一些例子了。让我们从如何阅读现有的 PDF 文档开始:

PDDocument 文档=
PDDocument.load( "./test.pdf" );

  上面的语句解析指定的PDF文件并在内存中创建其文档对象。考虑到处理大文档时的效率问题,PDFBox仅将文档结构存储在内存中,图像、嵌入字体和页面内容等对象将缓存在临时文件中。
  注意:当PDDocument对象使用完毕后,需要调用其close()方法来释放创建时使用的资源。
  

文本提取和 Lucene 集成

  这是一个信息检索时代,无论信息存储在什么介质中,应用程序都应该支持检索和索引。将信息组织和分类为可搜索的格式至关重要。这对于文本文档和HTML文档来说非常简单,但是PDF文档包含大量的结构和元信息,提取文档内容绝非一件简单的事情。 PDF 语言与 Postscript 类似,两者的对象都在页面上的某些位置绘制为矢量。例如:

  1. /Helv 12 Tf
  2. 0 13.0847 Td
  3. (你好世界)Tj

  上面的命令将字体设置为 12 Helvetica,将其移动到下一行并打印“Hello World”。这些命令流通常是压缩的,文本在屏幕上出现的顺序不一定是字符在文件中出现的顺序。因此,有时您无法直接从原始 PDF 文档中提取字符串。然而,PDFBox 复杂的文本提取算法允许开发人员提取文档内容,就像它出现在阅读器中一样。
  Lucene 是 Apache Jakarta 项目的子项目,Apache Jakarta 项目是一个流行的开源搜索引擎库。开发者可以使用Lucene创建索引,并根据索引对大量文本内容进行复杂的检索。 Lucene仅支持文本内容的检索,因此开发者需要将其他形式的数据转换为文本形式才能使用Lucene。例如,Microsoft Word 和 StarOffice 文档都必须先转换为文本形式,然后才能添加到 Lucene 索引中。
  PDF 文件也不例外,但 PDFBox 提供了一个特殊的集成对象,可以非常轻松地将 PDF 文档包含在 Lucene 索引中。将基本 PDF 文档转换为 Lucene 文档只需要一条语句:

文档 doc = LucenePDFDocument.getDocument( file );

  该语句解析指定的PDF文档,提取其内容并创建Lucene文档对象。然后您可以将该对象添加到 Lucene 索引中。如上所述,PDF文档还包含作者信息和关键字等元数据,在索引PDF文档时跟踪这些元数据非常重要。表 1 列出了 PDFBox 在创建 Lucene 文档时将填充的字段。

  这种集成使开发人员可以轻松使用 Lucene 来支持 PDF 文档的检索和索引。当然,某些应用程序需要更复杂的文本提取方法。这时可以直接使用PDFTextStripper类或者继承该类来满足这种复杂的需求。
  通过继承PDFTextStripper并重写showCharacter()方法,您可以通过多种方式控制文本提取。例如,限制使用 x,y 位置信息来提取特定的文本块。您可以有效地忽略 y 坐标大于某个值的所有文本,从而将文档标题内容排除在外。
  另一个例子。经常会发生这样的情况:从表单创建一组 PDF 文档,但原始数据丢失。也就是说,这些文档都包含一些您感兴趣的文本,并且这些文本位于相似的位置,但填充文档的表单数据丢失了。例如,您有一些在同一位置包含姓名和地址信息的信封。这时,你可以使用PDFTextStripper的派生类来提取所需的字段。这个类就像一个捕获屏幕区域的设备。
  

加密/解密

  PDF 的一项流行功能可让您加密文档内容、控制访问并限制读取未加密的文档。 PDF 文档使用主密码和可选的用户密码进行加密。如果设置了用户密码,PDF 阅读器(例如 Acrobat)将在显示文档之前提示输入密码。主密码用于授权对文档内容的修改。
  PDF 规范允许 PDF 文档的创建者限制用户使用 Acrobat reader 查看文档时的某些操作。这些限制包括:

  • 打印
  • 修改内容
  • 摘录内容

  PDF 文档安全性的讨论超出了本文的范围。有兴趣的读者可以参考PDF规范的相关部分。 PDF 文档的安全模型是可插拔的,您在加密文档时可以使用不同的安全处理程序。就本文而言,PDFBox 支持标准安全处理程序,这是大多数 PDF 文档所使用的。
  加密文档时,必须先指定安全处理器,然后使用主密码和用户密码进行加密。在下面的代码中,文档已加密,用户无需键入即可在 Acrobat 中打开它(未设置用户密码),但无法打印文档。

//加载文档
PD 文档 pdf =
PDDocument.load(“测试.pdf”);
//创建加密选项
PDStandardEncryption 加密选项 =
新的 PDStandardEncryption();
加密选项.setCanPrint(false);
pdf.setEncryptionDictionary(
加密选项);
//加密文档
pdf.加密(“主”,空);
//保存加密后的文档
//到文件系统
www.sychzs.cn("test-output.pdf");

  有关更详细的示例,请参阅 PDFBox 版本中包含的加密工具类源代码:org.pdfbox.Encrypt。
  许多应用程序可以生成 PDF 文档,但不支持控制文档的安全选项。这时可以使用PDFBox来拦截并加密PDF文档,然后再将其发送给用户。
  

形成整合

  当应用程序的输出是一系列表单字段值时,需要提供将表单保存到文件的功能。这时PDF技术将是一个不错的选择。开发人员可以手动编写 PDF 指令来绘制图形、表格和文本。或者将数据保存为 XML 并使用 XSL-FO 模板创建 PDF 文档。然而,这些方法耗时、容易出错且灵活性较差。对于简单的表单,更好的方法是创建模板,然后使用给定的输入数据填充模板以生成文档。
  就业资格验证是大多数人都熟悉的形式。它也称为“I-9 表格”,请参阅:http://www.sychzs.cn/graphics/formsfee/forms/files/i-9.pdf
  您可以使用包含在PDFBox 分发:

  1. java org.pdfbox.examples.fdf.PrintFields i-9.pdf

   还有一个以文本形式将数据插入指定字段的示例程序:

  1. java org.pdfbox.examples.fdf.SetField i-9.pdf NAME1 Smith

  在 Acrobat 中打开此 PDF 文档,您将看到“姓氏”字段已被填写。您还可以使用以下代码来完成相同的操作:

PD文档 pdf =
PDDocument.load(“i-9.pdf”);
PDDocumentCatalog docCatalog =
pdf.getDocumentCatalog();
PDAcroForm acroForm =
docCatalog.getAcroForm();
PDField 字段 =
acroForm.getField(“NAME1”);
field.setValue(“史密斯”);
www.sychzs.cn(“i-9-copy.pdf”);

 

  以下代码可用于提取您刚刚填写的表单字段的值:

PDField 字段 =
acroForm.getField(“NAME1”);
系统.out.println(
“名字=”field.getValue());

  

  Acrobat 支持将表单数据导入或导出为特定文件格式“表单数据格式”。此类文件有两种类型:FDF 和 XFDF。 FDF 文件以与 PDF 相同的格式存储表单数据,而 XFDF 以 XML 格式存储表单数据。 PDFBox 在一个类中处理 FDF 和 XFDF:FDFDocument。下面的代码片段演示了如何从上面的 I-9 表格导出 FDF 数据:

PD文档 pdf =
PDDocument.load(“i-9.pdf”);
PDDocumentCatalog docCatalog =
pdf.getDocumentCatalog();
PDAcroForm acroForm =
docCatalog.getAcroForm();
FDFDocument fdf = acroForm.exportFDF();
www.sychzs.cn(“exportedData.fdf”);

  

  PDFBox表单集成步骤:

  1. 使用 Acrobat 或其他可视化工具创建 PDF 表单模板
  2. 记下每个所需表单字段的名称
  3. 将模板存储在应用程序可以访问的位置
  4. 请求PDF时使用PDFBox解析PDF模板
  5. 填写指定的表格字段
  6. 将填写的结果(PDF)返回给用户

  

演示

1。创建 PDF 文件

 1 public void createHelloPDF() {
 2 PDDocument 文档 = null;
 3 PDPage页面=null;
 45 尝试{
 6 doc = new PDDocument();
 7 页 = new PDPage();
 8 doc.addPage(页面);
 9 PDFont 字体 = PDType1Font.HELVETICA_BOLD;
10 PDPageContentStream 内容 = new PDPageContentStream(doc, page);
11 内容.beginText();
12 content.setFont(字体, 12);
13 内容.moveTextPositionByAmount(100, 700);
14 内容.drawString("你好");
15
16. 内容.endText();
17 内容.close();
18 www.sychzs.cn("F:\\java56班\\eclipse-SDK-4.2-win32\\pdfwithText.pdf");
19 doc.close();
20 } catch (异常 e) {
21 系统.out.println(e);
22}
23}

  

     2、读取PDF文件:

 1 public void readPDF() {
 2 PDDocument helloDocument = null;
 3 尝试{
 4 helloDocument = PDDocument.load(新文件(5 "F:\\java56班\\eclipse-SDK-4.2-win32\\pdfwithText.pdf"));
 6 PDFTextStripper textStripper = new PDFTextStripper("GBK");
 7 System.out.println(textStripper.getText(helloDocument));
 8
 9 helloDocument.close();
10 } catch (IOException e) {
11 // TODO 自动生成的 catch 块
12 e.printStackTrace();
13}
14}

  

    3、修改PDF文件(处理中文乱码,我可以搞定的):

 1 /**
 2 * 找到 PDF 中的字符串并将其替换为新字符串。
 3 *
 4 * @param inputFile 要打开的 PDF。
 5 * @param outputFile 要写入的 PDF。
 6 * @param strToFind 要在 PDF 文档中查找的字符串。
 7 * @param message 要写入文件的消息。
 8 *
 9 * @throws IOException 如果写入数据时发生错误。
10 * @throws COSVisitorException 如果写入 PDF 时出现错误。
11*/12 public void doIt(字符串输入文件,字符串输出文件,字符串strToFind,字符串消息)
13 抛出 IOException、COSVisitorException
14{
15 // 文档
16 PDDocument 文档 = null;
17 尝试
18{
19 doc = PDDocument.load( 输入文件 );
20 // PDFTextStripper stripper=new PDFTextStripper("ISO-8859-1");
21 列表页面 = doc.getDocumentCatalog().getAllPages();
22 for( int i=0; i


    4、在PDF中加入图片:

 1 /**2 * 将图像添加到现有 PDF 文档。
 3 *
 4 * @param inputFile 要添加图像的输入 PDF。
 5 * @param image 要放入 PDF 中的图像的文件名。
 6 * @param outputFile 要写入 pdf 的文件。
 7 *
 8 * @throws IOException 如果写入数据时发生错误。
 9 * @throws COSVisitorException 如果写入 PDF 时出现错误。
10*/
11 公共无效createPDFFromImage(字符串输入文件,字符串图像,字符串输出文件)
12 抛出 IOException、COSVisitorException
13{
14 // 文档
15 PDDocument 文档 = null;
16 尝试
17{
18 doc = PDDocument.load( 输入文件 );
19
20 //我们将把图像添加到第一页。
21 PDPage 页 = (PDPage)doc.getDocumentCatalog().getAllPages().get( 0 );
22
23 PDXObjectImage ximage = null;24 if( image.toLowerCase().endsWith( ".jpg" ) )
25{
26 ximage = new PDJpeg(doc, new FileInputStream( image ) );
27}
28 else if (image.toLowerCase().endsWith(".tif") || image.toLowerCase().endsWith(".tiff"))
29{
30 ximage = new PDCcitt(doc, new RandomAccessFile(new File(image),"r"));
31}
32 其他
33{
34 BufferedImage awtImage = www.sychzs.cn( 新文件( 图像 ) );
35 ximage = new PDPixelMap(doc, awtImage);
36}
37 PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true);
38
39 //contentStream.drawImage(ximage, 20, 20 );
40 // 受http://www.sychzs.cn/a/22318681/535646启发的更好方法
41浮子刻度=0.5f; // 如果图像太大则减小该值42 System.out.println(ximage.getHeight());
43 System.out.println(ximage.getWidth());
44 // ximage.setHeight(ximage.getHeight()/5);
45 // ximage.setWidth(ximage.getWidth()/5);
46 contentStream.drawXObject(ximage, 20, 200, ximage.getWidth()*scale, ximage.getHeight()*scale);
47
48. 内容流.close();
49 www.sychzs.cn( 输出文件 );
50}
终于51了
52{
53 if( 文档!= null )
54{
55. 关闭();
56}
57}
58}

  

     5、PDF文件转换为图片:

 

 1 公共无效 toImage() {
 2 尝试{
 3 PDDocument 文档 = PDDocument
 4 .load("F:\\java56班\\eclipse-SDK-4.2-win32\\pdfwithText.pdf");
 5 int pageCount = doc.getPageCount();
 6 System.out.println(pageCount);
 7 列表页面 = doc.getDocumentCatalog().getAllPages();8 for (int i = 0; i 

  

6.将图片转换为PDF文件(支持将多张图片转换为PDF文件):

 1 /**
 2 * 根据 PDF 文件格式规范创建第二个示例文档。
 3*
 4 * @param 文件
 5 * 将 PDF 写入的文件。
 6 * @参数图像
 7 * 要放入 PDF 中的图像的文件名。
 8 *
 9 * @抛出IOException
10 * 如果写入数据出错。
11 * @抛出COSVisitorException
12 * 如果写入 PDF 时出现错误。
13*/
14 public void createPDFFromImage(String file, String image) 抛出 IOException, COSVisitorException {
15 //将多张图片转换为PDF文件
16 PDDocument 文档 = null;
17 doc = new PDDocument();
18 PDPage页=null;
19 PDXObjectImage ximage = null;20 PDPageContentStream 内容流 = null;
21
22 File 文件 = new File(image);
23 String[] a = 文件.list();
24 for (字符串字符串: a) {
25 if (string.toLowerCase().endsWith(".jpg")) {
26 字符串 temp = 图像 + "\\" + 字符串;
27 ximage = new PDJpeg(doc, new FileInputStream(temp));
28 页 = new PDPage();
29 doc.addPage(页面);
30 contentStream = new PDPageContentStream(文档,页面);
31浮子刻度=0.5f;
32 contentStream.drawXObject(ximage, 20, 400, ximage.getWidth()
33 * 缩放比例,ximage.getHeight() * 缩放比例);
34
35 PDFont字体= PDType1Font.HELVETICA_BOLD;
36. 内容流.beginText();
37 contentStream.setFont(字体, 12);
38 内容流.moveTextPositionByAmount(100, 700);39 内容流.drawString("你好");
40 内容流.endText();
41
42. 内容流.close();
43}
44}
45 www.sychzs.cn(文件);
46. 关闭();
47}

  

     7、替换PDF文件中的某个字符串:

 1 /**
 2 * 找到 PDF 中的字符串并将其替换为新字符串。
 3 *
 4 * @param inputFile 要打开的 PDF。
 5 * @param outputFile 要写入的 PDF。
 6 * @param strToFind 要在 PDF 文档中查找的字符串。
 7 * @param message 要写入文件的消息。
 8 *
 9 * @throws IOException 如果写入数据时发生错误。
10 * @throws COSVisitorException 如果写入 PDF 时出现错误。
11*/
12 public void doIt(字符串输入文件,字符串输出文件,字符串strToFind,字符串消息)
13 抛出 IOException、COSVisitorException
14{15 // 文档
16 PDDocument 文档 = null;
17 尝试
18{
19 doc = PDDocument.load( 输入文件 );
20 // PDFTextStripper stripper=new PDFTextStripper("ISO-8859-1");
21 列表页面 = doc.getDocumentCatalog().getAllPages();
22 for( int i=0; i

工具

  除了上面介绍的API之外,PDFBox还提供了一系列的命令行工具。表 2 列出了这些工具类并给出了简要介绍。

  

备注

  PDF规范共有1172页,其实现确实是一个巨大的工程。同样,PDFBox 版本指出它“正在进行中”,新功能将慢慢添加。它的主要弱点是从头开始创建 PDF 文档。然而,有几个开源 Java 项目可以填补这一空白。例如,Apache FOP 项目支持从描述要生成的 PDF 文档的特殊 XML 文档生成 PDF。此外,iText 还提供了用于创建表格和列表的高级 API。
  PDFBox 的下一版本将支持新的 PDF 1.5 对象流和交叉引用流。然后将提供对嵌入字体和图像的支持。在PDFBox的努力下,Java应用中的PDF技术有望得到全面支持。
  

参考资源

  PDFBox:www.sychzs.cn   Apache FOP:http://www.sychzs.cn/fop/   iText:www.sychzs.cn/iText/   PDF 参考:http:/ /www.sychzs.cn/asn/tech/pdf/specifications.jsp   Jakarta Lucene:http://www.sychzs.cn/lucene/

相关文章

最新资讯