如何用Java将PDF转换为文本(TXT)?

596 阅读8分钟

如何用Java将PDF转换为文本(TXT)

本文概述了从普通PDF文档中大规模提取纯文本的困难,并演示了两种有效执行该任务的API解决方案。

也许没有什么文件类型比可移植文档格式(PDF)更无处不在(通过设计)。PDF能够容纳各种令人印象深刻的内容/对象类型,并能在你能想到的任何操作系统上无缝工作,作为庞大的和/或特殊格式的文件的目标格式,PDF在个人和专业的项目景观中占据主导。例如,像PowerPoint的PPTX这样的文件类型通常非常大,将文件导出为PDF是使项目可共享的唯一有效方式;PDF的矢量和光栅图形功能提供了一个理想的解决方案,保持了原始文件的完美呈现,同时为共享实现了更好的压缩。像Microsoft Word DOCX这样的格式在许多操作系统上根本无法按原意打开;PDF版本很容易保留原件中包含的相同字体和格式编辑,使最终浏览者能够按原意看到文档的精确视觉呈现。将文件*插入PDF的便利之处不胜枚举。

如果说PDF文档有一个主要的缺点,那就是它们是出了名的难以编辑。事实上,几乎所有使 PDF 成为重新格式化外部/手动生成材料的理想解决方案的因素,反过来又使它们成为更具挑战性的操作格式之一。由于PDF在一个文件中处理了许多不同的内容类型,它们经过广泛的压缩以达到容易携带的大小,这意味着打开一个PDF文件并改变其内容从来都不是一个简单的任务。首先,它们被设计和编程为难以编辑,这并没有什么帮助;这也是使PDF成为安全可靠的格式的部分原因。

那么,如果你只是想从PDF中提取纯的、未格式化的文本--没有比这更特别的了呢?获取纯文本有很多原因,但以一种方便、可扩展的方式提取纯文本并不像看起来那么简单。如果你曾经试图通过--例如--匆忙地将PDF转换为办公文件格式(也许使用了网上数以百计的免费PDF转换工具之一)来提取文本,特别是在不知道原始文件格式是什么的情况下,你很可能经历过大量的格式不一致、奇怪的间距问题、缺少链接或媒体文件,以及随机的线条或表格漂浮在它们不应该出现的地方。当你只想要纯文本部分时,这种杂乱无章的情况会让你分心,而且你还得从新文件中分离出文本,并手动将其规范化。如果你试图用同样的工具从扫描或光栅化的PDF(完全由像素的二维图像组成)中提取文本,你可能已经注意到这根本不可能--至少,如果没有专门的光学字符识别(OCR)服务就不可能;这是一个非常独立的,但同样重要的PDF到文本问题的解决方案。当你试图从一个普通的PDF文档中获取纯文本时,你真正要做的是在PDF的许多可能的内容类型中分离出一个特定的片段,并保留其中的文本内容。此外,你要求该文本--它可能包含很多从微软Word等专有应用程序中编码的复杂格式--以任何平台上的人都能阅读的方式被规范化。

由于在PDF上执行简单的编辑任务相对困难,通常的做法是使用第三方PDF编辑器(或高级Adobe工具)来实现所需的结果。这些解决方案,虽然在逐个文件的基础上是有效的,但对于实现大规模的结果来说并不是很好--它们仍然需要手动浏览界面,这占用了大多数人的时间,不能浪费在大批量的转换任务上。

为了大规模地编辑和处理PDF,第三方API服务是最有效的解决方案。这是因为 PDF 编辑 API 可以与压缩的 PDF 文件进行通信,而不需要打开它;它们可以进行有意义的编辑(如旋转页面、删除注释等),在光谱的另一端,它们可以提取目标内容*,而*对原始文件根本没有任何影响。

示范

在本文的演示部分,我将引导你了解两个简单易用的API解决方案,它们被设计用来从普通的PDF文档中提取纯文本,而不需要打开或对原始文件做任何修改。这些API解决方案包括以下内容:

  1. 将PDF转换为文本(TXT)
  2. 按页转换PDF为文本(TXT)

上面列出的第一个解决方案将简单地从一个PDF文档中删除纯文本,而不执行任何额外的操作(默认情况下);API响应将包含一个'TextResult'字符串,其中包含提取的文本正文。下面,我附上一个响应模型供参考。

JSON

{
  "Successful": true,
  "TextResult": "string"
}

第二种解决方案,正如其名称所示,将删除文本,同时在结果中包括每部分文本来自的页码。这个解决方案对转换增加了更大的控制,确保产生的信息可以按照原始PDF文档的顺序进行交互,并且当我们以TXT形式存储时,更容易对转换后的信息进行分类。下面的模型显示了这个响应的格式。

JSON

{
  "Successful": true,
  "Pages": [
    {
      "PageNumber": 0,
      "PageText": "string"
    }
  ]
}

两种解决方案都提供了一个可选的 "textFormattingMode "参数,可以通过配置来指定转换时应该如何处理空白。当使用这个功能时,可能的值是 "保留空白",它将在文档中保留空白,并保留其与文本的相对位置,以及 "最小化空白",它在大多数情况下不会在文档中插入任何空格。默认设置是 "保留白色空间"。

下面,我将指导你如何利用这两个API的优势,使用Java中随时可以运行的补充代码示例。请注意,要免费使用这两个API,你只需要在www.cloudmersive.com上注册一个免费账户,以获得一个安全的API密钥(这个账户将产生每月800次的API调用限制)。

在调用这两个API之前,我们首先要进行SDK的安装。我们可以用Maven来做,首先在pom.xml中添加对资源库的引用。

XML

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

然后添加对pom.xml依赖性的引用。

XML

<dependencies>
<dependency>
    <groupId>com.github.Cloudmersive</groupId>
    <artifactId>Cloudmersive.APIClient.Java</artifactId>
    <version>v4.25</version>
</dependency>
</dependencies>

我们也可以用Gradle来做,在我们的根build.gradle中,在repositories的末尾加入它。

Groovy

allprojects {
	repositories {
		...
		maven { url 'https://jitpack.io' }
	}
}

然后在build.gradle中添加依赖关系。

Groovy

dependencies {
        implementation 'com.github.Cloudmersive:Cloudmersive.APIClient.Java:v4.25'
}

现在我们可以构建我们的API调用,从通用的PDF到TXT转换API开始。在下面的代码片断中,在文档指示的地方包括你的API密钥(就在进口下面),然后在下面的inputFile参数中包括你的文件路径。

Java

// Import classes:
//import com.cloudmersive.client.invoker.ApiClient;
//import com.cloudmersive.client.invoker.ApiException;
//import com.cloudmersive.client.invoker.Configuration;
//import com.cloudmersive.client.invoker.auth.*;
//import com.cloudmersive.client.ConvertDocumentApi;

ApiClient defaultClient = Configuration.getDefaultApiClient();

// Configure API key authorization: Apikey
ApiKeyAuth Apikey = (ApiKeyAuth) defaultClient.getAuthentication("Apikey");
Apikey.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//Apikey.setApiKeyPrefix("Token");

ConvertDocumentApi apiInstance = new ConvertDocumentApi();
File inputFile = new File("/path/to/inputfile"); // File | Input file to perform the operation on.
String textFormattingMode = "textFormattingMode_example"; // String | Optional; specify how whitespace should be handled when converting PDF to text.  Possible values are 'preserveWhitespace' which will attempt to preserve whitespace in the document and relative positioning of text within the document, and 'minimizeWhitespace' which will not insert additional spaces into the document in most cases.  Default is 'preserveWhitespace'.
try {
    TextConversionResult result = apiInstance.convertDocumentPdfToTxt(inputFile, textFormattingMode);
    System.out.println(result);
} catch (ApiException e) {
    System.err.println("Exception when calling ConvertDocumentApi#convertDocumentPdfToTxt");
    e.printStackTrace();
}

对于按页将PDF转换为文本的解决方案,请使用下面的代码段来代替。这将以与第一段相同的方式捕获你的API密钥和文件输入参数。

Java

// Import classes:
//import com.cloudmersive.client.invoker.ApiClient;
//import com.cloudmersive.client.invoker.ApiException;
//import com.cloudmersive.client.invoker.Configuration;
//import com.cloudmersive.client.invoker.auth.*;
//import com.cloudmersive.client.EditPdfApi;

ApiClient defaultClient = Configuration.getDefaultApiClient();

// Configure API key authorization: Apikey
ApiKeyAuth Apikey = (ApiKeyAuth) defaultClient.getAuthentication("Apikey");
Apikey.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//Apikey.setApiKeyPrefix("Token");

EditPdfApi apiInstance = new EditPdfApi();
File inputFile = new File("/path/to/inputfile"); // File | Input file to perform the operation on.
String textFormattingMode = "textFormattingMode_example"; // String | Optional; specify how whitespace should be handled when converting the document to text.  Possible values are 'preserveWhitespace' which will attempt to preserve whitespace in the document and relative positioning of text within the document, and 'minimizeWhitespace' which will not insert additional spaces into the document in most cases.  Default is 'preserveWhitespace'.
try {
    PdfTextByPageResult result = apiInstance.editPdfGetPdfTextByPages(inputFile, textFormattingMode);
    System.out.println(result);
} catch (ApiException e) {
    System.err.println("Exception when calling EditPdfApi#editPdfGetPdfTextByPages");
    e.printStackTrace();
}

记住,默认的textFormattingMode设置将在输出中保留输入PDF的空白。如果你希望避免这种情况,请确保将示例代码改为 "最小化空白"。有了这个解决方案,你就能轻松地将PDF文档中的文本重定向到各种不同的目的地,而不需要打开相关的文档。