当前位置: 首页 > news >正文

java 读取pdf文件内容_java读取pdf内容,零基础入门到精通,收藏这篇就够了

方式一

1、引入maven

<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.25</version> </dependency>

2、代码工具类

//import com.itextpdf.text.pdf.PdfReader; //import com.itextpdf.text.pdf.parser.PdfTextExtractor; //import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy; import com.google.common.collect.Lists; import com.jiayou.peis.entity.ImageObject; import org.apache.commons.io.FileUtils; import org.apache.pdfbox.Loader; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDResources; import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.pdmodel.graphics.PDXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImage; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.text.PDFTextStripper; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.*; import java.util.ArrayList; import java.util.List; /** * PDF处理 * */ public class PdfUtils { // /** // * 使用itextpdf提取PDF文本(解析不靠谱) // * // * @param inputStream // * @return // * @throws IOException // */ // @Deprecated // public static String toText(InputStream inputStream) throws IOException { // try { // StringBuilder buf = new StringBuilder(); // PdfReader reader = new PdfReader(inputStream); // int pageNum = reader.getNumberOfPages(); // for(int i=1;i<=pageNum;i++){ // // 读取第i页的文档内容 // buf.append(PdfTextExtractor.getTextFromPage(reader, i, new SimpleTextExtractionStrategy())); // } //// return buf.toString(); // return StrUtils.removeReturnChar(buf.toString()); // } finally { // CloseUtils.closeQuietly(inputStream); // } // } public static String text(byte[] data) throws IOException { return PdfUtils.text(data, true); } public static String text(byte[] data, boolean sortByPosition) throws IOException { ByteArrayInputStream inputStream = new ByteArrayInputStream(data); return PdfUtils.text(inputStream, sortByPosition); } /** * 使用pdfbox提取PDF文本(解析正常,可使用) * * @param file * @return * @throws IOException */ public static String text(File file, boolean sortByPosition) throws IOException { InputStream inputStream = new FileInputStream(file); return PdfUtils.text(inputStream, sortByPosition); } public static String text(File file) throws IOException { return PdfUtils.text(file, true); } public static String text(InputStream inputStream) throws IOException { return text(inputStream, true); } /** * 使用pdfbox提取PDF文本(解析正常,可使用) * * @param inputStream * @return * @throws IOException */ public static String text(InputStream inputStream, boolean sortByPosition) throws IOException { PDDocument document = null; try { // document = PDDocument.load(inputStream); document = Loader.loadPDF(inputStream); PDFTextStripper textStripper = new PDFTextStripper(); // Get total page count of the PDF document int numberOfPages = document.getNumberOfPages(); //set the first page to be extracted textStripper.setStartPage(1); // set the last page to be extracted textStripper.setEndPage(numberOfPages); // 获取文本内容 textStripper.setSortByPosition(sortByPosition); textStripper.setShouldSeparateByBeads(true); return StrUtils.removeReturnChar(textStripper.getText(document)); } finally { CloseUtils.closeQuietly(document, inputStream); } } /** * 使用pdfbox提取PDF文本(解析正常,可使用) * * @param file * @return * @throws IOException */ public static List<ImageObject> images(File file) throws IOException { InputStream inputStream = new FileInputStream(file); return PdfUtils.images(inputStream); } public static List<ImageObject> images(byte[] data) throws IOException { ByteArrayInputStream inputStream = null; try { inputStream = new ByteArrayInputStream(data); return PdfUtils.images(inputStream); } finally { CloseUtils.closeQuietly(inputStream); } } /** * 使用pdfbox提取PDF图片列表 * * @param inputStream * @return * @throws IOException */ public static List<ImageObject> images(InputStream inputStream) throws IOException { List<ImageObject> imageList = Lists.newArrayList(); PDDocument document = null; try { // document = PDDocument.load(inputStream); document = Loader.loadPDF(inputStream); // get resources for a page PDResources pdResources = document.getPage(0).getResources(); int i = 0; for (COSName csName : pdResources.getXObjectNames()) { // System.out.println(i+":"+csName); PDXObject pdxObject = pdResources.getXObject(csName); if (pdxObject instanceof PDImageXObject) { // i++; PDStream pdStream = pdxObject.getStream(); PDImageXObject image = new PDImageXObject(pdStream, pdResources); String imageSuffix = imageSuffix(image); // image storage location and image name BufferedImage bufferedImage = image.getImage(); ImageObject object = new ImageObject(); object.setIndex(i++); object.setImage(bufferedImage); object.setSuffix(imageSuffix); imageList.add(object); } } } finally { CloseUtils.closeQuietly(document, inputStream); } return imageList; } /** * 获取图片后缀 * * @param pdImage * @return * @throws IOException */ private static String imageSuffix(PDImageXObject pdImage) throws IOException { String suffix = pdImage.getSuffix(); if (suffix == null || "jb2".equals(suffix)) { suffix = "png"; } else if ("jpx".equals(suffix)) { // use jp2 suffix for file because jpx not known by windows suffix = "jp2"; } if (hasMasks(pdImage)) { // TIKA-3040, PDFBOX-4771: can't save ARGB as JPEG suffix = "png"; } return suffix; } private static boolean hasMasks(PDImage pdImage) throws IOException { if (pdImage instanceof PDImageXObject) { PDImageXObject ximg = (PDImageXObject) pdImage; return ximg.getMask() != null || ximg.getSoftMask() != null; } return false; } /** * 保存图片到指定文件夹 * * @param imageList * @param dir * @param prefixName * @throws IOException */ public static void saveImage(List<ImageObject> imageList, String dir, String prefixName) throws IOException { File imgDir = new File(dir); FileUtils.forceMkdir(imgDir); for(ImageObject image:imageList){ File imgFile = new File(dir, prefixName+"_"+image.getIndex()+"."+image.getSuffix()); ImageIO.write(image.getImage(), image.getSuffix(), imgFile); } } }

3、相关代码

CloseUtils
import java.io.Closeable; import java.util.zip.ZipInputStream; /** * 关闭文件流 */ public class CloseUtils { /** * 关闭文件流 * * @param closeables */ public static void closeQuietly(Closeable... closeables) { if (closeables != null && closeables.length > 0) { for (Closeable closeable : closeables) { if (closeable != null) { try { closeable.close(); } catch (Exception e) {} } } } } public static void closeEntryQuietly(ZipInputStream... closeables) { if (closeables != null && closeables.length > 0) { for (ZipInputStream closeable : closeables) { if (closeable != null) { try { closeable.closeEntry(); } catch (Exception e) { } } } } } }
StrUtils
import cn.hutool.core.util.StrUtil; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** * */ public class StrUtils { /** * * @param text * @return */ public static List<String> lines(String text){ if(text == null || text.isEmpty()){ return null; } return Lists.newArrayList(text.split("\n+")); } /** * * @param text * @param lineIndex * @return */ public static String splitAt(String text, int lineIndex){ if(text == null || text.isEmpty()){ return null; } String[] lines = text.split("\\s+"); return lines.length > lineIndex ? lines[lineIndex] : null; } /** * 读取某行的数据 * * @param text * @param lineIndex 0 开始 * @return */ public static String lineAt(String text, int lineIndex){ if(text == null || text.isEmpty()){ return null; } String[] lines = text.split("\r?\n"); return lines.length > lineIndex ? lines[lineIndex] : null; } /** * * * @param text * @param startFlag 最后开始第一个 * @param closeFlag 最后开始第一个 * @return */ public static String substringBetween(String text, String startFlag, String closeFlag, String subType){ return substringBetween(text, startFlag, closeFlag, subType, null); } /** * * * @param text * @param startFlag 最后开始第一个 * @param closeFlag 最后开始第一个 * @return */ public static String substringBetween(String text, String startFlag, String closeFlag, String subType, String defaultVal){ if(StringUtils.isEmpty(text)){ return defaultVal; } if("substringBetween".equals(subType)){ if(StringUtils.isNotEmpty(startFlag) && StringUtils.isNotEmpty(closeFlag)){ return StrUtils.substringBetween(text, startFlag, closeFlag); } } else if("substringBetweenLast".equals(subType)){ if(StringUtils.isNotEmpty(startFlag) && StringUtils.isNotEmpty(closeFlag)){ return StrUtils.substringBetweenLast(text, startFlag, closeFlag); } } else if("substringBetweenLastBefore".equals(subType)){ if(StringUtils.isNotEmpty(startFlag) && StringUtils.isNotEmpty(closeFlag)){ return StrUtils.substringBetweenLastBefore(text, startFlag, closeFlag); } } else if("substringBetweenBeforeLast".equals(subType)){ if(StringUtils.isNotEmpty(startFlag) && StringUtils.isNotEmpty(closeFlag)){ return StrUtils.substringBetweenBeforeLast(text, startFlag, closeFlag); } } else if("substringAfter".equals(subType)){ if(StringUtils.isNotEmpty(startFlag)){ return StringUtils.substringAfter(text, startFlag); } } else if("substringAfterLast".equals(subType)){ if(StringUtils.isNotEmpty(startFlag)){ return StringUtils.substringAfterLast(text, startFlag); } } else if("substringBefore".equals(subType)){ if(StringUtils.isNotEmpty(closeFlag)){ return StringUtils.substringBefore(text, closeFlag); } } else if("substringBeforeLast".equals(subType)){ if(StringUtils.isNotEmpty(closeFlag)){ return StringUtils.substringBeforeLast(text, closeFlag); } } return defaultVal; } /** * * @param text * @param startFlag 前面开始第一个 * @param closeFlag 前面开始第一个 * @return */ public static String substringBetween(String text, String startFlag, String closeFlag){ if(text == null || text.isEmpty()){ return null; } int startIndex = text.indexOf(startFlag); int endIndex = text.indexOf(closeFlag); if(startIndex >= 0 && endIndex >= 0 && endIndex >= startIndex){ return text.substring(startIndex+startFlag.length(), endIndex); } return null; } public static String substringBetween(String text, String startFlag){ if(text == null || text.isEmpty()){ return null; } int startIndex = text.indexOf(startFlag); if(startIndex >= 0 && startIndex != -1){ return text.substring(startIndex + startFlag.length()); } return null; } /** * * * @param text * @param startFlag 最后开始第一个 * @param closeFlag 最后开始第一个 * @return */ public static String substringBetweenLast(String text, String startFlag, String closeFlag){ if(text == null || text.isEmpty()){ return null; } int startIndex = text.lastIndexOf(startFlag); int endIndex = text.lastIndexOf(closeFlag); if(startIndex >= 0 && endIndex >= 0 && endIndex >= startIndex){ return text.substring(startIndex+startFlag.length(), endIndex); } return null; } /** * * * @param text * @param startFlag 最后开始第一个 * @param closeFlag 前面开始第一个 * @return */ public static String substringBetweenLastBefore(String text, String startFlag, String closeFlag){ if(text == null || text.isEmpty()){ return null; } int startIndex = text.lastIndexOf(startFlag); int endIndex = text.indexOf(closeFlag); if(startIndex >= 0 && endIndex >= 0 && endIndex >= startIndex){ return text.substring(startIndex+startFlag.length(), endIndex); } return null; } /** * * @param text * @param startFlag 前面开始第一个 * @param closeFlag 最后开始第一个 * @return */ public static String substringBetweenBeforeLast(String text, String startFlag, String closeFlag){ if(text == null || text.isEmpty()){ return null; } int startIndex = text.indexOf(startFlag); int endIndex = text.lastIndexOf(closeFlag); if(startIndex >= 0 && endIndex >= 0 && endIndex >= startIndex){ return text.substring(startIndex+startFlag.length(), endIndex); } return null; } /** * Null转换成空 * * @param val * @return */ public static String nullToEmpty(String val){ return val == null ? "" : val; } /** * 删除回车键 * 回车Carriage Return * * @param val * @return */ public static String removeReturnChar(String val){ return val == null ? "" : val.replace("\r", ""); } public static String getLastNotNullText(String[] array){ List<String> collect = Arrays.stream(array).filter(x -> StrUtil.isNotBlank(x)).collect(Collectors.toList()); return collect.get(collect.size() - 1); } public static String getFirstNotNullText(String[] array){ List<String> collect = Arrays.stream(array).filter(x -> StrUtil.isNotBlank(x)).collect(Collectors.toList()); return collect.get(0); } }

方式二

https://blog.csdn.net/ThinkPet/article/details/131256428

Java开发的就业市场正在经历结构性调整,竞争日益激烈

传统纯业务开发岗位(如仅完成增删改查业务的后端工程师)的需求,特别是入门级岗位,正显著萎缩。随着企业技术需求升级,市场对Java人才的要求已从通用技能转向了更深入的领域经验(如云原生、微服务)或前沿的AI集成能力。这也导致岗位竞争加剧,在一、二线城市,求职者不仅面临技术内卷,还需应对学历与项目经验的高门槛。

大模型为核心的AI领域正展现出前所未有的就业热度与人才红利

2025年,AI相关新发岗位数量同比激增543%,单月增幅最高超过11倍,大模型算法工程师位居热门岗位前列。行业顶尖人才的供需严重失衡,议价能力极强,跳槽薪资涨幅可达30%-50%。值得注意的是,市场并非单纯青睐算法研究员,而是急需能将大模型能力落地于复杂业务系统的工程人才。这使得具备企业级架构思维和复杂系统整合经验的Java工程师,在向“Java+大模型”复合人才转型时拥有独特优势,成为企业竞相争夺的对象,其薪资天花板也远高于传统Java岗位。

说真的,这两年看着身边一个个搞Java、C++、前端、数据、架构的开始卷大模型,挺唏嘘的。大家最开始都是写接口、搞Spring Boot、连数据库、配Redis,稳稳当当过日子。

结果GPT、DeepSeek火了之后,整条线上的人都开始有点慌了,大家都在想:“我是不是要学大模型,不然这饭碗还能保多久?”

先给出最直接的答案:一定要把现有的技术和大模型结合起来,而不是抛弃你们现有技术!掌握AI能力的Java工程师比纯Java岗要吃香的多。

即使现在裁员、降薪、团队解散的比比皆是……但后续的趋势一定是AI应用落地!大模型方向才是实现职业升级、提升薪资待遇的绝佳机遇!

如何学习AGI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版CSDN大礼包:《AGI大模型学习资源包》免费分享**

一、2025最新大模型学习路线

一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。

我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

L1级别:AI大模型时代的华丽登场

L1阶段:我们会去了解大模型的基础知识,以及大模型在各个行业的应用和分析;学习理解大模型的核心原理,关键技术,以及大模型应用场景;通过理论原理结合多个项目实战,从提示工程基础到提示工程进阶,掌握Prompt提示工程。

L2级别:AI大模型RAG应用开发工程

L2阶段是我们的AI大模型RAG应用开发工程,我们会去学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。

L3级别:大模型Agent应用架构进阶实践

L3阶段:大模型Agent应用架构进阶实现,我们会去学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造我们自己的Agent智能体;同时还可以学习到包括Coze、Dify在内的可视化工具的使用。

L4级别:大模型微调与私有化部署

L4阶段:大模型的微调和私有化部署,我们会更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调;并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。

整个大模型学习路线L1主要是对大模型的理论基础、生态以及提示词他的一个学习掌握;而L3 L4更多的是通过项目实战来掌握大模型的应用开发,针对以上大模型的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。

二、大模型经典PDF书籍

书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础(书籍含电子版PDF)

三、大模型视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

四、大模型项目实战

学以致用,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

五、大模型面试题

面试不仅是技术的较量,更需要充分的准备。

在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版CSDN大礼包:《AGI大模型学习资源包》免费分享

http://www.jsqmd.com/news/288617/

相关文章:

  • 盘点东北资质齐全的路虎改装公司,排名靠前的有哪些?
  • 2026柔性夹爪品牌选型指南:十大品牌全景评测,精准适配智造需求
  • 2026岩棉/玻镁/泡沫夹芯板厂家推荐,专业生产,品质可靠
  • 防锈膜品牌制造商哪家性价比高,天津金盛昱塑料制品有答案
  • 2026年1月四川绵阳旧楼加装电梯、老房加装电梯、加装电梯公司综合推荐
  • 详细介绍:5. MariaDB 数据库管理
  • 2026年柔性夹爪品牌综合实力榜:十大品牌全景透视与选型指南
  • git官方库PaddleOCR提供的几种模型库;github拉下来的源码和pip包(CLI)使用;supervisorctl部署踩坑;PaddleOCR文本检测模块训练实战(踩坑)
  • 2026东四省最新艺考集训学校 TOP5 评测!辽宁、沈阳等地优质培训机构权威榜单发布,助力艺考生升学梦想
  • uni-app 不同页面EventChannel通信
  • 超越期待:为什么说上海博禹泵业是国产水泵的“性价比王牌”?
  • 【ACM出版】第七届计算机信息和大数据应用国际学术会议(CIBDA 2026)
  • 文档识别架构思路整理;
  • 2026年苏州夹爪供应商深度解析:谁将成为您的柔性自动化伙伴?
  • 2025年电滑环市场占有率排行出炉,滑环/旋转接头/集电环/电环/气路滑环/光电滑环,电滑环源头厂家哪家权威
  • 2026聚乙烯蜡/氧化聚乙烯蜡/裂解聚乙烯蜡厂家推荐,专业生产,品质可靠
  • 2026年广州口碑好的Drupal服务企业排行榜,哪家性价比高?
  • 评测报告:浙江广告公司在品牌塑造中的角色与价值,当下广告优质品牌选购指南
  • 监控指标
  • YOLOv9 Torchaudio安装必要性:音频模块是否冗余?
  • 光伏线缆制造厂哪个值得选,品恩泰克品质保障受认可
  • FSMN-VAD服务守护:后台常驻进程配置教程
  • 2026年浑南专业的车衣改色实体店推荐榜单,车衣改色/太阳膜/贴车衣/汽车车衣/隐形车衣/汽车贴膜,车衣改色定制哪家好
  • 沪苏浙皖设备模型服务商推荐,聚景模型上榜了吗?
  • 2025浙江山地速降基地大揭秘!口碑爆棚的TOP5来袭,山地速降/山地车骑行/山地车/户外骑行,山地速降基地口碑推荐
  • 在线教育平台应用:学生答题语气分析提升教学反馈
  • Qwen模型并发能力不足?多实例负载均衡部署方案
  • 为什么Qwen3-14B适合中小企业?低成本落地实战案例
  • 强烈安利10个AI论文工具,研究生搞定毕业论文!
  • 2026苏州靠谱的综合律师事务所推荐