java读取pdf(可分页读取)

本文介绍了使用Java的pdfbox库解析PDF文件并提取文本的方法,包括导入必要的包、实例化PDFParser和PDFTextStripper类,以及如何从PDF文件中获取纯文本内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此文非原创,来源:http://www.2cto.com/kf/201109/104526.html

 

需要pdfbox和log4j的包
举个例子:
import org.pdfbox.pdfparser.*;
import org.pdfbox.util.PDFTextStripper;
import java.io.*;
/**
 * 测试pdfbox
 * @author kingfish
 * @version 1.0
 */
public class TestPdf {
  public static void main(String[] args) throws Exception{
    FileInputStream fis = new FileInputStream("c://intro.pdf");
    PDFParser p = new PDFParser(fis);
    p.parse();   
    PDFTextStripper ts = new PDFTextStripper();   
    String s = ts.getText(p.getPDDocument());
    System.out.println(s);
    fis.close();
  }
}

--------------------------------------------------------------------------------

import java.io.*;
import java.util.*;
import com.etymon.pj.*;
import com.etymon.pj.object.*;
import com.etymon.pj.exception.*;
/**
* This is a wrapper for the Pj PDF parser
*/
public class PjWrapper {
Pdf pdf;
PjCatalog catalog;
PjPagesNode rootPage;
public PjWrapper(String PdfFileName,String TextFileName)throws
IOException, PjException {
pdf = new Pdf(PdfFileName);
// hopefully the catalog can never be a reference...
catalog = (PjCatalog) pdf.getObject(pdf.getCatalog());
// root node of pages tree is specified by a reference in the catalog
rootPage = (PjPagesNode) pdf.resolve(catalog.getPages());
}
public static void main (String [] args) throws IOException, PjException
{
/*PjWrapper testWrapper = new PjWrapper(args[0]);
LinkedList textList = testWrapper.getAllText();*/
}
/**
* Returns as much text as we can extract from the PDF.
* This currently includes:
*
* NOTE: Pj does not support LZW, so some text in some PDF's may not
* be indexable
*/
public LinkedList getAllText() throws PjException {
LinkedList stringList = new LinkedList();
Iterator streamIter = getAllContentsStreams().iterator();
PjStream stream;
String streamData;
String streamText;
boolean moreData;
int textStart, textEnd;
//System.out.println("Going through streams...");
while(streamIter.hasNext()) {
//System.out.println("Getting next stream");
stream = (PjStream) streamIter.next();
//System.out.println("Adding text from stream with filter: "
+getFilterString(stream);
stream = stream.flateDecompress();
//System.out.println("Adding text from stream with filter
afterdecompress: " + getFilterString(stream));
streamData = new String(stream.getBuffer());
streamText = new String();
moreData = true;
textStart = textEnd = 0;
while(moreData) {
if ((textStart = streamData.indexOf('(', textEnd + 1)) < 0) {
moreData = false;
break;
}
if ((textEnd = streamData.indexOf(')', textStart + 1)) < 0) {
moreData = false;
break;
}
try {
streamText +=
PjString.decodePdf(streamData.substring(textStart,textEnd + 1));
} catch (Exception e) {
System.out.println("malformed string: " +
streamData.substring(textStart, textEnd + 1));
}
}
//if(streamText.equals("inserted text"))
System.out.println(streamText);
if (streamText.length() > 0)
stringList.add(streamText);
}
return stringList;
}
public static String getFilterString(PjStream stream) throws PjException
{
String filterString = new String();
PjObject filter;
//System.out.println("getting filter from dictionary");
if ((filter = stream.getStreamDictionary().getFilter()) == null) {
//System.out.println("Got null filter");
return "";
}
//System.out.println("got it");
// filter should either be a name or an array of names
if (filter instanceof PjName) {
//System.out.println("getting filter string from simple name");
filterString = ((PjName) filter).getString();
} else {
//System.out.println("getting filter string from array of names");
Iterator nameIter;
Vector nameVector;
if ((nameVector = ((PjArray) filter).getVector()) == null) {
//System.out.println("got null vector for list of names");
return "";
}
nameIter = nameVector.iterator();
while (nameIter.hasNext()) {
filterString += ((PjName) nameIter.next()).getString();
if (nameIter.hasNext())
filterString += " ";
}
}
//System.out.println("got filter string");
return filterString;
}
/**
* Performs a post-order traversal of the pages tree
* from the root node and gets all of the contents streams
* @returns a list of all the contents of all the pages
*/
public LinkedList getAllContentsStreams() throws
InvalidPdfObjectException {
return getContentsStreams(getAllPages());
}
/**
* Get contents streams from the list of PjPage objects
* @returns a list of all the contents of the pages
*/
public LinkedList getContentsStreams(LinkedList pages) throws
InvalidPdfObjectException {
LinkedList streams = new LinkedList();
Iterator pageIter = pages.iterator();
PjObject contents;
while(pageIter.hasNext()) {
contents = pdf.resolve(((PjPage)pageIter.next()).getContents());
// should only be a stream or an array of streams (or refs to
streams)
if (contents instanceof PjStream)
streams.add(contents);
else{
Iterator streamsIter = ((PjArray)contents).getVector().iterator();
while(streamsIter.hasNext())
streams.add(pdf.resolve((PjObject)streamsIter.next()));
}
}
return streams ;
}
/**
* Performs a post-order traversal of the pages tree
* from the root node.
* @returns a list of all the PjPage objects
*/
public LinkedList getAllPages() throws InvalidPdfObjectException {
LinkedList pages = new LinkedList();
getPages(rootPage, pages);
return pages;
}
/**
* Performs a post-order traversal of the pages tree
* from the node passed to it.
* @returns a list of all the PjPage objects under node
*/
public void getPages(PjObject node, LinkedList pages) throws
InvalidPdfObjectException {
PjPagesNode pageNode = null;
// let's hope pdf's don't have pointers to pointers
if (node instanceof PjReference)
pageNode = (PjPagesNode) pdf.resolve(node);
else
pageNode = (PjPagesNode) node;
if (pageNode instanceof PjPage) {
pages.add(pageNode);
return;
}
// kids better be an array and not a reference to one
Iterator kidIterator = ((PjArray) ((PjPages)
pageNode).getKids()).getVector().iterator();
while(kidIterator.hasNext()) {
getPages((PjObject) kidIterator.next(), pages);
}
}
public Pdf getPdf() {
return pdf;
}
}

<think>好的,我现在需要回答用户关于Java读取PDF的问题。首先,我得确认用户的需求是什么。他们可能想了解如何在Java读取PDF文件的内容,可能需要具体的库或方法。 首先,我应该列出常用的Java库,比如Apache PDFBox、iText、PDFClown等。这些库各有特点,用户可能不知道哪个更适合他们的项目,所以需要简要介绍每个库的功能和适用场景。 接下来,我需要考虑用户可能的用途。例如,他们是否需要提取文本、处理表单数据,或者解析更复杂的元素。不同的库支持的功能不同,比如PDFBox适合文本提取,而iText更适合生成和操作PDF。 然后,我应该给出每个库的简单示例代码。比如,使用PDFBox读取文本的基本步骤,包括导入依赖、加载文档、提取文本并关闭资源。示例代码需要正确,并且符合用户的实际使用情况,比如Maven依赖的写法。 同时,要注意提到不同库的版本和许可证问题,尤其是iText的AGPL协议,这可能影响商业应用,用户需要知道选择合适的版本或遵守许可。 另外,可能需要提到一些注意事项,比如中文乱码问题,PDF的结构复杂性导致解析困难,以及处理加密PDF的情况。这些都是用户在实际操作中可能遇到的挑战,提前说明可以帮助他们避免问题。 最后,确保回答结构清晰,分点说明,使用代码块包裹示例,并给出建议,帮助用户根据需求选择合适的工具。要使用中文,避免术语混淆,保持语言简洁易懂。</think>在Java读取PDF文件通常需要借助第三方库,以下是逐步解决方案和常用工具介绍: 一、常用工具库 1. Apache PDFBox (推荐) - 开源免费(Apache 2.0协议) - 支持文本提取、内容操作、PDF生成 - 适用于:文本提取、内容分析、PDF转换 2. iText - 商业使用需注意AGPL协议 - 提供高级操作功能 - 适用于:PDF生成、表单处理 3. PDFClown - 开源(LGPL协议) - 支持内容修改和提取 - 适用于:内容操作、低级解析 二、实现步骤(以PDFBox为例) 1. 添加Maven依赖: ```xml <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.29</version> </dependency> ``` 2. 基础文本提取代码: ```java import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; public class PdfReader { public static void main(String[] args) { try (PDDocument document = PDDocument.load(new File("test.pdf"))) { PDFTextStripper stripper = new PDFTextStripper(); String text = stripper.getText(document); System.out.println(text); } catch (Exception e) { e.printStackTrace(); } } } ``` 三、注意事项 1. 编码问题 - 中文PDF需指定字体: ```java stripper.setSortByPosition(true); // 处理中文布局 ``` 2. 复杂内容处理 - 表格数据需要使用`PDFTableStripper`扩展 - 图片需用`PDFRenderer`提取 3. 加密文件处理 ```java if (document.isEncrypted()) { document.setSecurityHandler(new StandardDecryptionMaterial("password")); } ``` 四、性能优化建议 1. 大文件处理: - 使用`PDFTextStripper`的分页处理 - 启用内存映射: ```java MemoryUsageSetting.setupMainMemoryOnly(); ``` 五、替代方案对比 | 库名称 | 文本提取 | 内容修改 | 生成PDF | 学习曲线 | |------------|----------|----------|---------|----------| | PDFBox | 优秀 | 良好 | 良好 | 中等 | | iText | 良好 | 优秀 | 优秀 | 较高 | | PDFClown | 中等 | 优秀 | 支持 | 陡峭 | 建议根据具体需求选择: - 简单文本提取 → PDFBox - 复杂文档生成 → iText - 内容深度分析 → PDFClown 遇到具体问题时,可进一步探讨实现细节(如表格识别、水印处理等)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值