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

通过java将 word(.doc) 转 md

说明:使用的jdk8的版本

1、添加相关依赖

        <!-- Apache POI 处理Word文档 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>4.1.2</version></dependency>

2、实现代码

// 转换 .doc 格式文件public void convertDoc(String inputPath, String outputPath) throws IOException {try (HWPFDocument document = new HWPFDocument(new FileInputStream(inputPath));FileWriter writer = new FileWriter(outputPath)) {Range range = document.getRange();for (int i = 0; i < range.numParagraphs(); i++) {Paragraph para = range.getParagraph(i);String text = para.text().trim();if (text.isEmpty()) continue;// 处理标题String mdText = processDocHeading(para, text);if (mdText != null) {writer.write(mdText + "\n\n");continue;}// 处理列表mdText = processDocList(para, text);if (mdText != null) {writer.write(mdText + "\n\n");continue;}// 普通段落 自定义过滤条件if (!text.contains("页 共")){writer.write(text + "\n\n");}}}}// 处理 .doc 标题private String processDocHeading(Paragraph para, String text) {int styleIndex = para.getStyleIndex();// 标题样式索引通常为 0-5 对应 1-6 级标题if (styleIndex >= 0 && styleIndex <= 5) {if (text.contains("?")){//自定义过滤条件return repeat("#", styleIndex + 1) + " " + text;//styleIndex + 1表示从标题1开始}}return null;}// 处理 .doc 列表private String processDocList(Paragraph para, String text) {// 兼容处理列表判断,避免使用可能不存在的方法try {// 通过反射检查是否有 getListFormat 方法Object listFormat = para.getClass().getMethod("getListFormat").invoke(para);if (listFormat != null) {// 检查是否有列表编号Object listNumber = listFormat.getClass().getMethod("getListNumber").invoke(listFormat);if (listNumber instanceof Integer && (Integer) listNumber > 0) {return "- " + text;}}} catch (Exception e) {// 没有列表格式,返回 null}return null;}@Testpublic  void a() {try {// 转换.doc文件  第一个参数是word文件所在路径,第二个是希望输出的文件路径及命名convertDoc("C:\\***\\***.doc", "D:\\***\\output_from_doc.md");log.info("转换完成");}catch (Exception e){log.error("转换失败:"+e);}}

3、自此,转换已完成,若想要docx格式的转md 可参考下面

import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumPr;import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;public class WordToMarkdown {// 转换 .doc 格式文件public void convertDoc(String inputPath, String outputPath) throws IOException {try (HWPFDocument document = new HWPFDocument(new FileInputStream(inputPath));FileWriter writer = new FileWriter(outputPath)) {Range range = document.getRange();for (int i = 0; i < range.numParagraphs(); i++) {Paragraph para = range.getParagraph(i);String text = para.text().trim();if (text.isEmpty()) continue;// 处理标题String mdText = processDocHeading(para, text);if (mdText != null) {writer.write(mdText + "\n\n");continue;}// 处理列表mdText = processDocList(para, text);if (mdText != null) {writer.write(mdText + "\n\n");continue;}// 普通段落writer.write(text + "\n\n");}}}// 转换 .docx 格式文件public void convertDocx(String inputPath, String outputPath) throws IOException {try (XWPFDocument document = new XWPFDocument(new FileInputStream(inputPath));FileWriter writer = new FileWriter(outputPath)) {for (XWPFParagraph para : document.getParagraphs()) {String text = para.getText().trim();if (text.isEmpty()) continue;// 处理标题String mdText = processDocxHeading(para, text);if (mdText != null) {writer.write(mdText + "\n\n");continue;}// 处理列表mdText = processDocxList(para, text);if (mdText != null) {writer.write(mdText + "\n\n");continue;}// 普通段落writer.write(text + "\n\n");}}}// 处理 .doc 标题private String processDocHeading(Paragraph para, String text) {int styleIndex = para.getStyleIndex();// 标题样式索引通常为 0-5 对应 1-6 级标题if (styleIndex >= 0 && styleIndex <= 5) {return repeat("#", styleIndex + 1) + " " + text;}return null;}// 处理 .doc 列表private String processDocList(Paragraph para, String text) {// 兼容处理列表判断,避免使用可能不存在的方法try {// 通过反射检查是否有 getListFormat 方法Object listFormat = para.getClass().getMethod("getListFormat").invoke(para);if (listFormat != null) {// 检查是否有列表编号Object listNumber = listFormat.getClass().getMethod("getListNumber").invoke(listFormat);if (listNumber instanceof Integer && (Integer) listNumber > 0) {return "- " + text;}}} catch (Exception e) {// 没有列表格式,返回 null}return null;}// 处理 .docx 标题private String processDocxHeading(XWPFParagraph para, String text) {String styleName = para.getStyle();if (styleName != null && styleName.startsWith("Heading")) {try {int level = Integer.parseInt(styleName.replaceAll("[^0-9]", ""));if (level >= 1 && level <= 6) {return repeat("#", level) + " " + text;}} catch (NumberFormatException e) {// 忽略格式错误的标题}}return null;}// 处理 .docx 列表private String processDocxList(XWPFParagraph para, String text) {CTP ctp = para.getCTP();if (ctp == null) return null;CTPPr pPr = ctp.getPPr();if (pPr == null) return null;CTNumPr numPr = pPr.getNumPr();if (numPr != null) {return "- " + text;}return null;}// 字符串重复方法(兼容 JDK8)private String repeat(String str, int times) {if (times <= 0) return "";StringBuilder sb = new StringBuilder();for (int i = 0; i < times; i++) {sb.append(str);}return sb.toString();}public static void main(String[] args) {WordToMarkdown converter = new WordToMarkdown();try {// 转换 .doc 文件converter.convertDoc("input.doc", "output_doc.md");// 转换 .docx 文件converter.convertDocx("input.docx", "output_docx.md");System.out.println("转换完成!");} catch (IOException e) {System.err.println("转换失败:" + e.getMessage());e.printStackTrace();}}
}

http://www.dtcms.com/a/314710.html

相关文章:

  • Java数组转换为逗号分隔字符串的方法
  • dbeaver导入数据及配置讲解
  • 通过 Flink 和 CDC 从 Oracle 数据库获取增量数据,并将这些增量数据同步到 MySQL 数据库中
  • Go 与 Python 爬虫代码实操对比
  • # 自动定时运行Python爬虫脚本教程(Windows任务计划程序)
  • LED光源模拟太阳光,全新科技照亮未来
  • 解决 GitLab external_url 修改无效的问题:保留数据重新生成配置
  • 一(2)关于单链表中的疑问 head = head->next; 和 head->next = head 的核心区别
  • 张宇高数基础30讲与1000题学习笔记(第4-6章)
  • LeetCode:219.存在重复元素||220.存在重复元素|||
  • SpringDoc OpenAPI 3 和 TestContainers 的 零配置自动化API测试方案,实现从API文档生成
  • 安全策略实验报告
  • ensp防火墙用户认证综合实验
  • AI开灯的几种方法,与物理世界的交互过渡
  • 生成式人工智能展望报告-欧盟-06-深度调研-医疗、教育、网络安全
  • 《红色脉络:一部PLMN在中国的演进史诗 (1G-6G)》 第4篇 | 专题:多址技术——频谱资源“共享”的艺术 (FDMA/TDMA/CDMA)
  • 3.JVM,JRE和JDK的关系是什么
  • 《Python 实用项目与工具制作指南》· 1.1 安装Python
  • Jeston + TensorRT + Realsense D435i + ROS noetic + Yolo11 各版本模型目标检测
  • Go 函数选项模式
  • Nature Commun:电化学可及性新策略!PEDOT限域COF孔道提升铀电沉积效率46倍
  • Sklearn 机器学习 数据聚类 肘部法则选择聚类数目
  • 二叉树的概念以及二叉树的分类,添加,删除
  • 机器学习通关秘籍|Day 02:特征降维、用KNN算法和朴素贝叶斯实现分类
  • MySql的两种安装方式
  • AI编程助手:终结996的新希望
  • (论文速读)关注特征细化的图像恢复自适应稀疏变换
  • mac 锁屏不断网 2025
  • C++进阶-封装红黑树模拟实现map和set(难度较高)
  • 量子计算接口开发:Python vs Rust 性能对决