JAVA:探索 PDF 文字提取的技术指南

1、简述

随着信息化的发展,PDF 文档成为了信息传播的重要媒介。在许多应用场景下,如数据迁移、内容分析和信息检索,我们需要从 PDF 文件中提取文字内容。JAVA提供了多种库来处理 PDF 文件,其中 PDFBox 和 iText 是最常用的两个。

在这里插入图片描述

在这篇博客中,我们将深入探讨如何使用多种方式来提取 PDF 文本,分析各自的优缺点,并讨论在不同场景下的最佳实践。

2、准备工作

在开始之前,你需要以下准备工作:

  • 百度开发者账号:前往百度AI开放平台注册账号,并创建一个应用以获取 API Key 和 Secret Key。
  • Java 开发环境:确保你的开发环境已经配置好,包括 JDK 和一个集成开发环境(IDE),如 IntelliJ IDEA 或 Eclipse。
  • 引入依赖:百度官方提供了 Java SDK,或者你可以直接使用 HttpClient 进行 API 调用。

引入Maven依赖:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.7</version>
</dependency>
<dependency><groupId>org.apache.directory.studio</groupId><artifactId>org.apache.commons.codec</artifactId><version>1.8</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version>
</dependency>
<!-- spring-boot-actuator -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.2</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version>
</dependency>
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>4.5.0</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>font-asian</artifactId><version>7.1.16</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>kernel</artifactId><version>7.1.16</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>io</artifactId><version>7.1.16</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>layout</artifactId><version>7.1.16</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>forms</artifactId><version>7.1.16</version>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>pdfa</artifactId><version>7.1.16</version>
</dependency>
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.8.0</version>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version>
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>

3、利用 PDFBox 解析

可以使用 PDFBox 库来解析 PDF 文件并提取文本内容。PDFBox 可以帮助你逐行读取 PDF 的文本,然后你可以编写逻辑来查找指定的文字。

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;import java.io.File;
import java.io.IOException;public class PDFReader {public static void main(String[] args) {String filePath = "path/to/your/pdf-file.pdf";String keyword = "指定文字";  // 要查找的指定文字try (PDDocument document = PDDocument.load(new File(filePath))) {PDFTextStripper pdfStripper = new PDFTextStripper();String text = pdfStripper.getText(document);// 将文本按行分割String[] lines = text.split("\n");for (int i = 0; i < lines.length; i++) {if (lines[i].contains(keyword)) {System.out.println("在第 " + page + " 页找到关键字: " + keyword);}}} catch (IOException e) {e.printStackTrace();}}
}

4、利用 Tesseract 来解析 PDFBox

将 PDF 转换为图像并使用 Tesseract OCR 进行文本识别是一种有效的方法来处理 PDF 文档中的复杂布局或不规则表格。以下是如何在 Java 中实现这一过程的详细步骤:

  • 将 PDF 页面转换为图像:使用 PDFBox 将每个 PDF 页面转换为图像。
  • 使用 Tesseract OCR 识别图像中的文本:通过 Tesseract OCR 读取每个图像,并提取文本。
  • 查找关键字并提取信息:在 OCR 识别的文本中查找关键字(如“图号”),并提取相邻单元格的值。
 @PostMapping("/pdf2Excel")public ResponseEntity<String> pdf2Excel(@RequestParam("keyword") String keyword, @RequestParam("file")MultipartFile file) throws IOException {if (file.isEmpty()) {return new ResponseEntity<>("File is empty", HttpStatus.BAD_REQUEST);}String basePath = System.getProperty("java.io.tmpdir");String imagesPath = basePath + "\\images\\";File directory = new File(imagesPath);if(!directory.exists()){directory.mkdirs();}File convFile = new File(basePath+ "/" + file.getOriginalFilename());file.transferTo(convFile);String excelPath = "C:\\Users\\WIN10\\Desktop\\fsdownload\\excel\\MapData.xlsx";File excelFile = new File(excelPath);if(!excelFile.exists()){Files.createFile(excelFile.toPath());}Map<String, Object> objectMap = new HashMap<>();try (PDDocument document = Loader.loadPDF(convFile)) {PDFRenderer pdfRenderer = new PDFRenderer(document);int numberOfPages = document.getNumberOfPages();ITesseract instance = new Tesseract();instance.setDatapath("D:\\soft\\Tesseract-OCR\\tessdata"); // 设置Tesseract的tessdata路径instance.setLanguage("chi_sim"); // 设置识别语言for (int pageIndex = 0; pageIndex < numberOfPages; pageIndex++) {BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(pageIndex, 144);int currentPageNum = pageIndex + 1;File imageFile = new File(imagesPath + "page_" + currentPageNum + ".jpg");ImageIO.write(bufferedImage, "jpg", imageFile);// 调用OCR服务识别文字String result =  instance.doOCR(imageFile);processOCRResult(result, objectMap, currentPageNum);System.out.println("Page " + (currentPageNum) + " converted to image.");}System.out.println("获取所有的图号-结束");System.out.println("数据转换Excel-开始");// 创建 Excel 工作簿Workbook workbook = new XSSFWorkbook();Sheet sheet = workbook.createSheet("Map Data");// 创建表头Row headerRow = sheet.createRow(0);headerRow.createCell(0).setCellValue("Key");headerRow.createCell(1).setCellValue("Value");// 填充数据int rowNum = 1;for (Map.Entry<String, Object> entry : objectMap.entrySet()) {Row row = sheet.createRow(rowNum++);row.createCell(0).setCellValue(entry.getKey());row.createCell(1).setCellValue((String) entry.getValue());}// 自动调整列宽sheet.autoSizeColumn(0);sheet.autoSizeColumn(1);FileOutputStream fileOut = new FileOutputStream(excelFile);workbook.write(fileOut);workbook.close();return ResponseEntity.ok().body("数据转换Excel成功");} catch (Exception e) {return new ResponseEntity<>("File upload error: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);}}

4、利用百度文字识别来解析 PDFBox

在现代开发中,文字识别(OCR,Optical Character Recognition)技术已经被广泛应用于图像处理、文档管理等领域。百度提供的文字识别 API 功能强大、易于使用,能够帮助开发者快速实现图像中的文字提取。本文将介绍如何在 Java 中利用百度文字识别 API 进行图片文字提取。

4.1 获取 Access Token

在调用文字识别 API 之前,需要先获取 Access Token。这一步通常在应用初始化时执行,并且 Access Token 具有一定的有效期。

public  Map<String,Object> token() throws Exception {//获取当前配置表数据参数Map<String,Object> map  = new HashMap<>();CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost httpPost = new HttpPost("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials");httpPost.addHeader("Content-Type", "application/json");httpPost.addHeader("Accept", "application/json");//post请求参数配置List<NameValuePair> formparams = new ArrayList<NameValuePair>();formparams.add(new BasicNameValuePair("client_id", API_KEY));formparams.add(new BasicNameValuePair("client_secret", SECRET_KEY));UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");   //设置编码格式为utf-8httpPost.setEntity(uefEntity);  //设置POST请求参数//使用httpclient的execute方法发送接口请求CloseableHttpResponse response =  httpClient.execute(httpPost);HttpEntity  httpEntity = response.getEntity();String responseString = EntityUtils.toString(httpEntity);JSONObject obj = JSON.parseObject(responseString);if(response.getStatusLine().getStatusCode() == 200){map.put("access_token", obj.getString("access_token"));map.put("refresh_token",obj.getString("refresh_token"));map.put("expires_in",obj.getIntValue("expires_in"));}else {map.put("error", obj.getString("error"));map.put("error_description", obj.getString("error_description"));}map.put("stateCode", response.getStatusLine().getStatusCode());return map;
}
4.2 调用百度文字识别 API

获取到 Access Token 后,我们可以使用它来调用百度的文字识别 API。我们将通过一个 POST 请求发送图片数据,并接收识别结果。

public Map<String,Object> accurate(String token , String image) throws Exception{Map<String,Object> map  = new HashMap<>();CloseableHttpClient httpClient = HttpClients.createDefault();HttpPost httpPost = new HttpPost("https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + token+"&language_type=CHN_ENG&detect_direction=false&paragraph=false&probability=false");httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");httpPost.addHeader("Accept", "application/json");//post请求参数配置List<NameValuePair> formparams = new ArrayList<NameValuePair>();formparams.add(new BasicNameValuePair("image", image));UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8");   //设置编码格式为utf-8httpPost.setEntity(uefEntity);  //设置POST请求参数//使用httpclient的execute方法发送接口请求CloseableHttpResponse response =  httpClient.execute(httpPost);HttpEntity  httpEntity = response.getEntity();String responseString = EntityUtils.toString(httpEntity);JSONObject obj = JSON.parseObject(responseString);String errorCode = obj.getString("error_code");if(Objects.nonNull(errorCode)){map.put("stateCode", 500);map.put("error_code", obj.getString("error_code"));map.put("error_msg", obj.getString("error_msg"));}else {map.put("stateCode", 200);map.put("words_result", obj.getJSONArray("words_result"));map.put("words_result_num",obj.getString("words_result_num"));map.put("log_id",obj.getString("log_id"));}return map;
}
4.3 将识别的文字转成 Excel

百度 OCR API 返回的结果是 JSON 格式的。我们可以使用 Gson 或其他 JSON 解析库来处理这些结果,并提取出识别到的文字并转成Excel输出。

@PostMapping("/pdf2Excel")
public ResponseEntity<byte[]> pdf2Excel(@RequestParam("keyword") String keyword, @RequestParam("file") MultipartFile file) throws Exception {if (file.isEmpty()) {return new ResponseEntity<>("File is empty".getBytes(), HttpStatus.BAD_REQUEST);}String basePath = System.getProperty("java.io.tmpdir");String imagesPath = basePath + "\\images\\";File directory = new File(imagesPath);if(!directory.exists()){directory.mkdirs();}File convFile = new File(basePath+ "/" + file.getOriginalFilename());file.transferTo(convFile);Map<String, Object> tokenMap = ocrAPIFactory.token();int stateCode = (int)tokenMap.get("stateCode");if(stateCode != 200){return  new ResponseEntity<>("ERROR".getBytes(), HttpStatus.OK);}Map<Integer, String> objectMap = new HashMap<>();String accessToken= String.valueOf(tokenMap.get("access_token"));System.out.println("获取所有的图号-开始");try (PDDocument document = Loader.loadPDF(convFile)) {PDFRenderer pdfRenderer = new PDFRenderer(document);int numberOfPages = document.getNumberOfPages();for (int pageIndex = 0; pageIndex < numberOfPages; pageIndex++) {BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(pageIndex, 144);int currentPageNum = pageIndex + 1;String imageFilePath = imagesPath + "page_" + currentPageNum + ".jpg";File imageFile = new File(imageFilePath);ImageIO.write(bufferedImage, "jpg", imageFile);String imgStr =  ocrAPIFactory.getFileContentAsBase64(imageFilePath, false);Map<String, Object> fileMap = ocrAPIFactory.accurate(accessToken, imgStr);stateCode = (int)fileMap.get("stateCode");if(stateCode != 200){System.out.println ("获取百度OCR 百度文件转换失败:" + fileMap.get("error_msg"));return  new ResponseEntity<>("ERROR".getBytes(), HttpStatus.OK);}JSONArray wordsResults = (JSONArray)fileMap.get("words_result");if(Objects.nonNull(wordsResults)){processOCRResult(wordsResults, currentPageNum, objectMap);}System.out.println("Page " + (currentPageNum) + " converted to image.");}System.out.println("获取所有的图号-结束");System.out.println("数据转换Excel-开始");//页数排序Map<Integer, String> sortedMap = objectMap.entrySet().stream() // 将 Map 转换为 Stream.sorted(Map.Entry.comparingByKey()) // 按值排序.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue,(oldValue, newValue) -> oldValue, // 如果有重复键时的合并策略() -> new LinkedHashMap<>()  // 保持顺序的 Map 实现));// 创建 Excel 工作簿Workbook workbook = new XSSFWorkbook();Sheet sheet = workbook.createSheet("Map Data");// 创建表头Row headerRow = sheet.createRow(0);headerRow.createCell(0).setCellValue("页码");headerRow.createCell(1).setCellValue("图号");// 填充数据int rowNum = 1;for (Map.Entry<Integer, String> entry : sortedMap.entrySet()) {Row row = sheet.createRow(rowNum++);row.createCell(0).setCellValue(Objects.nonNull(entry.getKey()) ? entry.getKey().toString() :"0");row.createCell(1).setCellValue(Objects.nonNull(entry.getValue()) ? entry.getValue().toString() :"" );}// 自动调整列宽sheet.autoSizeColumn(0);sheet.autoSizeColumn(1);// 将工作簿内容写入字节数组输出流ByteArrayOutputStream outputStream = new ByteArrayOutputStream();try {workbook.write(outputStream);workbook.close();} catch (IOException e) {e.printStackTrace();return ResponseEntity.status(500).build();}// 创建 Http 响应HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);headers.setContentDispositionFormData("attachment", "MapData.xlsx");System.out.println("数据转换Excel-结束");//删除文件夹try {// 递归删除文件夹及其内容Files.walkFileTree(new File(imagesPath).toPath(), new SimpleFileVisitor<Path>() {@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Files.delete(file);return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {Files.delete(dir);return FileVisitResult.CONTINUE;}});System.out.println("Directory deleted successfully.");} catch (IOException e) {e.printStackTrace();}return ResponseEntity.ok().headers(headers).body(outputStream.toByteArray());} catch (Exception e) {System.out.println("数据转换Excel异常:" + e);return new ResponseEntity<>("File upload error: ".getBytes(), HttpStatus.INTERNAL_SERVER_ERROR);}
}

5、结论

在 Java 中,PDF 文字提取可以通过 PDFBox 轻松实现。PDFBox 适合简单的文档处理,复杂的文档结构通过OCR来解析。在选择使用哪个库时,建议根据项目需求、文档复杂度和性能要求进行评估。

这篇博客提供了从 PDF 中提取文字的基础方法,并介绍了如何处理复杂的文档结构。希望这对你的项目有所帮助!如果有任何问题或建议,欢迎留言讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/475739.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3+vant实现弹幕循环播放~

1、效果图 <!-- 弹幕 --> <div style"height: 88px"><van-barragev-model"list"duration"5000":rows"rows":gap"gap":loop"loop"style"--move-distance: -345px" ><div class&quo…

南京邮电大学算法设计-二叉树先序遍历算法动态演示

二叉树先序遍历算法动态演示 一、课题内容和要求 (1)实验目的&#xff1a; 本实验通过手动输入二叉树结点信息&#xff0c;构建相应的二叉树&#xff0c;并通过图形化界面动态演示先序遍历算法的过程。通过本次实验&#xff0c;我可以深入理解二叉树的数据结构、先序遍历算法…

大数据挖掘期末复习

大数据挖掘 数据挖掘 数据挖掘定义 技术层面&#xff1a; 数据挖掘就是从大量的、不完全的、有噪声的、模糊的、随机的实际应用数据中&#xff0c;提取隐含在其中、人们事先不知道的、但又潜在有用的信息的过程。 数据准备环节 数据选择 质量分析 数据预处理 数据仓库 …

【Anomaly Detection论文阅读记录】Resnet网络与WideResNet网络

Resnet网络 网络结构&#xff1a;(层数计算不包括max pool、average pool、softmax等操作) 层数计算&#xff08;以Resnet-18为例子&#xff09;&#xff1a; conv1conv2_xconv3_xconv4_xconv5_xfc1(22)(22)(22)(22)118 WideResNet网络 WideResNet提出了一种新的体系结构&#…

基于YOLOv8深度学习的汽车车身车损检测系统研究与实现(PyQt5界面+数据集+训练代码)

本文研究并实现了一种基于YOLOV8深度学习模型的汽车车身车损检测系统&#xff0c;旨在解决传统车损检测中效率低、精度不高的问题。该系统利用YOLOV8的目标检测能力&#xff0c;在单张图像上实现了车身损坏区域的精确识别和分类&#xff0c;尤其是在车身凹痕、车身裂纹和车身划…

【前端学习笔记】Javascript学习二(运算符、数组、函数)

一、运算符 运算符&#xff08;operator&#xff09;也被称为操作符&#xff0c;是用于实现赋值、比较和执行算数运算等功能的符号。 JavaScript中常用的运算符有&#xff1a; 算数运算符、递增和递减运算符、比较运算符、逻辑运算符、赋值运算符 算数运算符&#xff1a; 、-…

python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具

python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具 文章目录 python实战案例----使用 PyQt5 构建简单的 HTTP 接口测试工具项目背景技术栈用户界面核心功能实现结果展示完整代码总结 在现代软件开发中&#xff0c;测试接口的有效性与响应情况变得尤为重要。本文将指导…

网络安全之信息收集-实战-1

请注意&#xff0c;本文仅供合法和授权的渗透测试使用&#xff0c;任何未经授权的活动都是违法的。 实战&#xff1a;补天公益src“吉林通用航空职业技术学院” 奇安信&#xff5c;用户登录https://www.butian.net/Loo/submit?cid64918 域名或ip&#xff1a;https://www.jlth…

鸿蒙实战:使用隐式Want启动Ability

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙应用项目2.2 修改Index.ets代码2.3 创建LuzhouAbility2.4 创建Luzhou页面2.5 设置模块配置文件 3. 测试效果4. 实战总结 1. 实战概述 本次鸿蒙应用实战&#xff0c;先创建项目“ImplicitWantStartAbility”&#xff0c;接着修改In…

STM32低功耗设计NFC与无线距离感应智能钥匙扣-分享

目录 目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 1.电路图采用Altium Designer进行设计&#xff1a; 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 智能钥匙扣作为一种小巧而实用的智能设备&#xff0c;凭借其便携性…

【Node.js】Node.js 和浏览器之间的差异

Node.js 是一个强大的运行时环境&#xff0c;它在现代 JavaScript 开发中扮演着重要角色。然而&#xff0c;许多开发者在使用 Node.js 时常常会感到困惑&#xff0c;尤其是与浏览器环境的对比。本文将深入探讨 Node.js 和浏览器之间的差异&#xff0c;帮助你全面理解两者的设计…

qt之telnet连接目标设备在线调试功能

一、前言 在QT下使用telnet连接目标设备&#xff0c;进行在线命令调试&#xff0c;也可配合ftp或ssh使用。 telnet某些库在qt5下不可用&#xff0c;无法获取登录信息&#xff0c;只能获取到连接信息&#xff0c;这里我用自己的方式判断是否成功登录 二、环境 window qt5.7…

小熊派Nano接入华为云

一、华为云IoTDA创建产品 创建如下服务&#xff0c;并添加对应的属性和命令。 二、小熊派接入 根据小熊派官方示例代码D6完成了小熊派接入华为云并实现属性上传命令下发。源码&#xff1a;小熊派开源社区/BearPi-HM_Nano 1. MQTT连接代码分析 这部分代码在oc_mqtt.c和oc_mq…

Hbuilder X/Uniapp 关于app运行调试及mumu模拟器运行问题

Hbuilder X 关于app调试问题及mumu模拟器链接问题 Hbuilder 关于app调试问题1. app运行配置2. adb路径配置3. 模拟器端口查询4. 运行 Hbuilder 关于app调试问题 1. app运行配置 Hbuilder > 工具 > 设置 > 运行配置 adb路径配置&#xff08;见2&#xff09; Android模…

MySQL-关键字执行顺序

&#x1f496;简介 在MySQL中&#xff0c;SQL查询语句的执行遵循一定的逻辑顺序&#xff0c;即使这些关键字在SQL语句中的物理排列可能有所不同。 &#x1f31f;语句顺序 (8) SELECT (9) DISTINCT<select_list> (1) FROM <left_table> (3) <join_type> JO…

【SpringBoot】26 实体映射工具(MapStruct)

Gitee 仓库 https://gitee.com/Lin_DH/system 介绍 现状 为了让应用程序的代码更易于维护&#xff0c;通常会将项目进行分层。在《阿里巴巴 Java 开发手册》中&#xff0c;推荐分层如下图所示&#xff1a; 每层都有对应的领域模型&#xff0c;即不同类型的 Bean。 DO&…

RPC-健康检测机制

什么是健康检测&#xff1f; 在真实环境中服务提供方是以一个集群的方式提供服务&#xff0c;这对于服务调用方来说&#xff0c;就是一个接口会有多个服务提供方同时提供服务&#xff0c;调用方在每次发起请求的时候都可以拿到一个可用的连接。 健康检测&#xff0c;能帮助从连…

Enterprise Architect 16 下载、安装与无限30天操作

文章目录 Enterprise Architect 16 简介&#xff08;一&#xff09;支持多种建模语言和标准&#xff08;二&#xff09;强大的版本控制、协作和文档管理功能&#xff08;三&#xff09;增强的技术和用户体验&#xff08;四&#xff09;高级功能和扩展性 一&#xff0c;下载软件…

小程序租赁系统开发为企业提供高效便捷的租赁服务解决方案

内容概要 在这个数字化飞速发展的时代&#xff0c;小程序租赁系统应运而生&#xff0c;成为企业管理租赁业务的一种新选择。随着移动互联网的普及&#xff0c;越来越多的企业开始关注如何利用小程序来提高租赁服务的效率和便捷性。小程序不仅可以为用户提供一个快速、易用的平…

定时器的小应用

第一个项目 第一步&#xff0c;RCC开启时钟&#xff0c;这个基本上每个代码都是第一步&#xff0c;不用多想&#xff0c;在这里打开时钟后&#xff0c;定时器的基准时钟和整个外设的工作时钟就都会同时打开了 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);第二步&…