Java PDFBox - 读取和修改带有特殊字符(变音符号)的 pdf

2024-03-08

我正在尝试使用此方法修改 pdf(第一个代码块 - 使用 PDFStreamParser 并迭代 PDFOperator,然后在需要时更新 COSString):

http://www.coderanch.com/t/556009/open-source/PdfBox-Replace-String-double-pdf http://www.coderanch.com/t/556009/open-source/PdfBox-Replace-String-double-pdf

我遇到了一些 UTF-8 字符(变音符号)的问题:当我打印要更新的文本时,它显示为“Societ??ii Na?ionale”(其中“?”是类似 0002 或 0004 的代码) )。

有趣的是:

  1. 当我编写更新的 pdf 文件时,字符显示正确(即使我无法检测并替换它们)
  2. 如果我尝试使用 PDFTextStripper 的 getText(...) 剥离文本,则文本将被完美提取。
  3. 我尝试了 2 个 pdfbox 版本:1.5.0(其行为如上所述)和 1.8.1(最终的书面 pdf 文件无法正确显示特殊字符,并且文档中出现“空”字符串)

我可以为用于更新 pdf 的类做什么(配置)(或者至少尝试...)以便正确显示所有 UTF-8 字符?

EDIT:

Screenshot: enter image description here

EDIT 2:

我搜索了 PDFTextStripper 及其超类中的 pdfbox 源代码,发现了文本是如何提取的:

在 processStream 方法的开头,我们有

graphicsState = new PDGraphicsState(aPage.findCropBox());

当剥离 processEncodedText 中的文本时,使用 PDFont 类的实例,如下所示:

final PDFont font = graphicsState.getTextState().getFont();

文本是从 byte[] 中提取的:

String c = font.encode( string, i, codeLength );

新问题是,当我使用相同的两行代码实例化 PDFont 类时,我得到一个“null”字体类,因此我无法使用 .encode(...) 方法。 这些类的源代码在这里:http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFStreamEngine.java http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFStreamEngine.java and http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFTextStripper.java http://grepcode.com/file/repo1.maven.org/maven2/org.apache.pdfbox/pdfbox/1.5.0/org/apache/pdfbox/util/PDFTextStripper.java

我现在正在挖掘更多...


您不能只替换字符串中的文本。我不是轻易说这句话的。我很多年前曾经使用过Acrobat,并且在最初的版本中做过文本搜索工具,所以我对文本编码的问题有相当深刻的了解。主要问题是 PDF 中的每个字符串都以某种方式编码。这是因为 PDF 是在 Unicode 普遍可用之前创建的,并且在 PostScript 中已有历史。 PosctScript 喜欢拥有非常灵活的字体编码方法,并鼓励重新编码。

因此,让我们退一步来了解整个情况。

默认情况下,PDF 中要使用文本运算符显示的字符串中的字符被编码为一系列 8 位字符。为了确定为每个字节绘制什么字形,该字节被推入该字体的编码向量。编码向量将字节映射到字形名称,然后在字体中查找该字形名称并将其绘制在页面上。请注意,这个描述是半真半假的(稍后会详细介绍)。

大多数生成 PDF 的应用程序都很友好,只使用标准编码,例如StandardEncoding or WinAnsiEncoding,其中大部分都是相当合理的。其他人将使用标准编码以及编码增量这是标准编码与编码内容的差异。

一些应用程序试图在生成的 PDF 中更加节俭,因此它们会查看所使用的字形并决定嵌入字体的子集。如果他们只使用大写和小写罗马字母和数字,他们会在没有这些元素的情况下重建字体,并可能选择重新索引它们并提供编码向量,以便字节 0x00 转到字形“a”,而 0x01 转到字形“a”。字形“b”等。

现在回到一半的真相。有一类字体是通过字符 ID(或 CID)编码的,TrueType 和 OpenType 字体就属于该类。在这种情况下,您可以访问 Unicode,但同样有一个编码步骤,您将字符串(现在是 UTF16BE)映射到 CID,CID 用于从字体获取字形。没有什么特别好的理由,Adobe 使用 PostScript 函数来进行映射。再说一遍,这是一个 3/4 的事实,因为对于中文、日文和韩文字体的旧管理也有不同的编码。

因此,在您轻松地将字符放入 PDF 字体的字符串中之前,您必须问几个问题:

  1. 我的字形在字体中吗?
  2. 我的字形在编码中吗?
  3. 我的字形的编码是什么?

其中任何一项都可能与您的预期不同。例如,如果您想输入 Ä(a diresis),您必须查看该字体是否具有其字形(可能不存在,因为该字体是子集)。那么字体可能有一个有趣的编码,可能不包括字形。最后,用于 Ä 的实际字节值可能不是标准的。

因此,当我看到有人试图简单地替换 PDF 内容中的一大块文本时,我看到的只是一个痛苦的世界。对于大多数正常的 PDF 来说,这在 90% 的情况下都有效,但对于任何奇异的东西 - 祝你好运。 PDF 的文本渲染怪癖已经足够让人痛苦了,以至于有时更容易将其视为只写格式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java PDFBox - 读取和修改带有特殊字符(变音符号)的 pdf 的相关文章

  • 在 Eclipse 中隐藏重复的工具栏项

    我不知道如何 但我的 STS 有重复的工具栏项目 我不知道如何删除它们 这是我复制的工具栏的样子 我想摆脱这些 我试图隐藏工具栏 但这没有帮助 有人知道如何删除重复的吗 自从升级到 Oxygen 以来 我一直遇到同样的问题 我无法可靠地重现
  • 最终字段可能尚未/已经初始化[重复]

    这个问题在这里已经有答案了 可能的重复 如何处理抛出检查异常的静态最终字段初始值设定项 https stackoverflow com questions 1866770 how to handle a static final field
  • 无法将 INode 类型值分配给 类型变量。为什么?

    我想知道为什么以下代码无法工作 public static
  • Ant 中回显目标描述

  • Java - toString 到 Color

    我一整天都在努力解决这个问题 基本上我做了一个 for 循环 将条目添加到数组列表中 其中一项是 颜色 变量 我已经用过random nextInt为颜色构造函数的红色 绿色和蓝色部分创建新值 我还设置了一个toString方法 这样我就可
  • 外部实体更改后索引不更新

    我目前正在开发一个项目 使用 JPA 2 1 保存数据并使用 hibernate search 4 5 0 final 搜索实体 映射类和索引后 搜索工作正常 但是 当我更改值时描述B 类从 someStr 到 anotherStr 数据库
  • 为本地@ExceptionHandler编写JUnit测试

    我有以下控制器 class Controller ResponseStatus HttpStatus OK RequestMapping value verifyCert method RequestMethod GET public vo
  • java 中的 Try-with-resources 和 return 语句

    我想知道是否放一个return里面的声明尝试资源block 防止资源自动关闭 try Connection conn return conn createStatement execute 如果我写这样的东西将会联系被关闭 Oracle 文
  • 在 Java 中的 JFrame/JPanel/JComponent 中添加 Web 浏览器

    我正在开发一个 Java 应用程序 需要在应用程序中使用 Web 浏览器 我见过一些应用程序这样做 例如在同一应用程序中单击左侧面板中的提要并打开右侧面板中的链接时的 RSS 阅读器 我想实现类似的功能 在java中可以做到这一点吗 Jav
  • 使用 equals 方法比较两个对象,Java

    我有一个对象数组 我想将它们与目标对象进行比较 我想返回与目标对象完全匹配的对象的数量 这是我的计数方法 public int countMatchingGhosts Ghost target int count 0 for int i 0
  • 开发人员实际上是否使用 vim 在 Windows 操作系统上编写代码(Java)? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Hazelcast:连接到远程集群

    我们有一组 Hazelcast 节点 全部运行在一个远程系统 具有许多节点的单个物理系统 上 我们希望从外部客户端连接到该集群 一个 Java 应用程序 它使用如下代码连接到 Hazelcast ClientConfig clientCon
  • 按名称获取 ArrayList

    这是正确的获取方式吗ArrayList
  • EJB 中 @Stateless 相对于 @Singleton 的真正用例是什么

    如果我正确理解EJB Singleton实际上与普通Java中的Singleton相同 也是spring中的单例 gt 一个实例 每个调用同时通过同一个实例 Stateless 声明一个 bean 它可以 但不得 具有多个实例 但限制是一个
  • Java8 项目上的 SonarQube 给出 jacoco-Exception

    我刚刚下载了最新版本 SonarQube 4 3 然后尝试使用以下命令构建 java 8 项目 mvn clean install mvn sonar sonar 这给了我下面的例外 谷歌搜索 我的印象是这是一个早期的问题 应该已经解决 h
  • Java:java.util.Preferences 失败

    我的程序将加密的产品密钥数据保存到计算机上java util Preferences类 系统首选项 而不是用户 问题是 在 Windows 和 Linux 上 尚未在 OSX 上测试过 但可能是相同的 如果我不运行该程序sudo或者具有管理
  • 如何在启用嵌入时间戳和 LTV 的情况下签署 PDF?

    我正在尝试签署启用了时间戳和 LTV 的 pdf 以便它在 Adob e Reader 中显示如下 在英语中 这意味着 签名包含嵌入的时间戳 和 签名启用了 LTV 这是我正在使用的代码 PrivateKey pk get pk from
  • 乔达时间中两个日期之间的天数

    如何找到两次之间的天数差异乔达时间 http www joda org joda time DateTime http www joda org joda time apidocs org joda time DateTime html实例
  • 如何在apache POI中读取excel文件的准确单元格内容

    当我读取单元格的内容时 例如如果它是日期格式 它会转换为另一个值 例如 12 31 2099 gt 46052 和 50 00 gt 50 和 50 00 gt 0 5 但我想要的是获取每个单元格的确切字符串值 我的代码是这样的 cell
  • 通过向上转换将 Java.sql.date 转换为 Java.util.date 安全吗?

    java sql date 扩展了 java util date 那么通过将 java sql date 转换为 java util date 是否可以在两者之间进行转换 或者有其他方法可以转换它们吗 您不一定需要强制转换 您可以将 SQL

随机推荐

  • 准备卸载,就像 Inno Setup 中的准备安装页面一样

    我需要检查多个 exe 文件是否正在运行 通过安装程序安装 然后提示用户关闭它们 如果它们正在运行 如果没有则取消卸载过程 有没有办法在安装中为卸载程序提供类似 准备 页面之类的内容 或者我该如何实施这样的检查 甚至一个消息框也将是完美的
  • Shapefile 到 TopoJSON 转换问题

    I m trying to convert a shapefile to GeoJSON and then to TopoJSON as described in Let s Make a Map http bost ocks org mi
  • 删除最后一次出现的字符

    A 今天在 talkstats com 上发现了这个问题 http www talkstats com showthread php 36897 regular expressions其中发布者想要使用正则表达式删除字符串的最后一个句点 而
  • 刷新jsp文件时线程锁定

    在重负载下 当 GZipping 和解压缩 JSP 文件时 我看到很多线程被锁定 线程转储如下所示 似乎来自大小为 14Kb 的 header jsp http 0 0 0 0 8080 304 daemon prio 3 tid 0x00
  • ASP.NET 页面上的 MS SQL 超时,但 SSMS 中没有

    当存储过程在我们的 ASP NET 页面之一上执行时 它在 SQL Server 上超时 但出现异常Timeout expired The timeout period elapsed prior to completion of the
  • 在 Python 中使用带有正则表达式的 OR 语句时防止列表中出现空元素

    我正在使用正则表达式从网站编译价格 PriceFinder re compile lt n s b d d 2 lt lt FF0000 gt b d d 2 lt Price re findall PriceFinder str soup
  • Cypher - 删除具有特定值的所有属性

    我正在寻找一种方法来删除数据库中任何节点的每个属性 使用 Cypher 具有特定值 Context我从关系表中获取了一个包含大量 NULL 值的 csv 批量文件 LOAD CSV将它们作为价值观 删除它们 用 csv 文件中的空 替换它们
  • 使用 ssh 检查远程主机上是否存在文件

    我想检查远程主机上是否存在某个文件 我试过这个 if ssh user localhost p 19999 e home user Dropbox path Research and Development Puffer and Traps
  • SQLSRV PHP for SQL Server 不是有效的 Win32 应用程序

    这是我的设置 Windows Server 2008 R2 64 位 阿帕奇 2 4 4 64 位 PHP 5 4 15 32位 64位仍处于实验阶段 线程安全 VC9编译器 Microsoft SQL Server 2012 本机客户端
  • 锚元素的 ping 属性跨浏览器如何?

    a 是 HTML5 锚元素中一个相对较新 相对未知的属性 它的跨浏览器兼容性如何 我查看了 MDN 等在线资源http caniuse com http caniuse com 但没有发现任何表明浏览器支持的信息 我想知道这是否是 2014
  • 在docker中安装.net框架4.7.2

    我是 Net 环境的新手 我正在尝试为我的公司实施 docker 他们之前使用的是 4 5 所以我在 dockerfile 中使用了以下语句 RUN Install WindowsFeature NET Framework 45 ASPNE
  • 如何设置Spark执行器内存?

    我已经设定Spark executor 内存 to 2048m 并且在 UI 环境 页面中 我可以看到该值已正确设置 但是在 Executors 页面中 我看到只有1个执行器 它的内存是265 4MB 非常奇怪的价值 为什么不是256MB
  • const char* 连接

    我需要连接两个 const 字符 如下所示 const char one Hello const char two World 我该怎么做呢 我通过了这些char 来自具有 C 接口的第三方库 所以我不能简单地使用std string反而
  • 显示所有 messageHeader 的值

    我想知道显示所有 MessageHeaders 服务器端的最佳方式是什么 实际上我知道的唯一方法如下 OperationContext Current IncomingMessageHeaders GetHeader
  • 将 Powershell 核心设置为 Windows/Linux 上的默认 GNU Make shell

    在 Windows 上的 makefile 中 使用以下 make 版本 PS C projects gt make version GNU Make 4 1 Built for i686 w64 mingw32 Copyright C 1
  • 一般:Angular2 中的异步验证

    从几个晚上开始 我就开始在 augular2 中进行表单验证 所有基本案例都很容易实现并且工作正常 但我坚持使用异步验证 我创建了一个非常小的例子http plnkr co edit Xo8xwJjhlHkXrunzS8ZE http pl
  • Z3 将数组的默认值设置为零

    我正在尝试求解数组表达式的模型 其中数组的默认值等于 0 例如 我正在尝试解决这个例子 但我总是得到未知的结果 declare const arr Array Int Int declare const arr2 Array Int Int
  • 如何获取函数签名对应的TypedDict?

    假设我有一个像这样的函数签名 def any foo bar Bar with baz Optional Baz None with datetime Optional datetime None effective Optional bo
  • 如何在asp.net中发送邮件

    你好 我编写了在asp net中发送邮件的代码 如下所示 MailMessage mailMessage new MailMessage mailMessage From email protected cdn cgi l email pr
  • Java PDFBox - 读取和修改带有特殊字符(变音符号)的 pdf

    我正在尝试使用此方法修改 pdf 第一个代码块 使用 PDFStreamParser 并迭代 PDFOperator 然后在需要时更新 COSString http www coderanch com t 556009 open sourc