Java 實現將Word 轉換成markdown

日常的開發中,需要將word 等各類文章信息轉換成格式化語言,因此需要使用各類語言將word 轉換成Markdown

1、引入 jar包

  <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency>

2、使用以下代碼進行編寫

package com.nd.ai.test.service.utils;import com.alibaba.fastjson.JSONObject;
import com.nd.ai.test.service.dto.apitest.FileMarkdownDTO;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.xwpf.usermodel.*;import java.io.*;
import java.util.List;
import java.util.UUID;/*** @ClassName WordToMarkdownConverter* @Author Administrator*/
public class WordToMarkdownConverter {public static FileMarkdownDTO convertWordToMarkdown(String wordPath) throws IOException {List<String> imagePathList = Lists.newArrayList();FileMarkdownDTO dto = new FileMarkdownDTO();try  {File file = new File(wordPath);String uuid = UUID.randomUUID().toString();String outputFilePath = file.getParent() + File.separator + uuid + ".md";File outputFile = new File(outputFilePath);FileInputStream fis = new FileInputStream(file); // Corrected to read the input fileXWPFDocument document = new XWPFDocument(fis);FileWriter writer = new FileWriter(outputFile);dto.setMdPath(outputFilePath);String imageDir = file.getParent() + File.separator + uuid + "-images";new File(imageDir).mkdirs(); // Create image directoryfor (IBodyElement element : document.getBodyElements()) {if (element instanceof XWPFParagraph) {processParagraph((XWPFParagraph) element, writer, imageDir, imagePathList);} else if (element instanceof XWPFTable) {processTable((XWPFTable) element, writer, imageDir, imagePathList);}}writer.close();// 增加讀取mardkown 文件內容// Read the content of the generated Markdown fileStringBuilder markdownContent = new StringBuilder();try (BufferedReader br = new BufferedReader(new FileReader(outputFile))) {String line;while ((line = br.readLine()) != null) {markdownContent.append(line).append("\n");}}dto.setMarkdownContent(markdownContent.toString());dto.setParserStatus("success");} catch (IOException e){dto.setParserStatus("error");throw new IOException(e);}dto.setFileImagePathList(imagePathList);return dto;}private static void processParagraph(XWPFParagraph paragraph, FileWriter writer, String imageDir,List<String> imageNamePath) throws IOException {String content = processParagraphContent(paragraph, imageDir,imageNamePath);if (content.isEmpty()) return;// 處理標題和列表樣式String style = paragraph.getStyle();if (style != null && style.startsWith("Heading")) {int level = Math.min(Character.getNumericValue(style.charAt(7)), 6);StringBuilder heading = new StringBuilder();for (int i = 0; i < level; i++) {heading.append("#");}heading.append(" ").append(content).append("\n\n");writer.write(heading.toString());
//            writer.write("#".repeat(level) + " " + content + "\n\n");} else if (isListParagraph(paragraph)) {String listMark = getListMark(paragraph);writer.write("* " + listMark + " " + content + "\n");} else {writer.write(content + "\n\n");}}private static String getListMark(XWPFParagraph para) {int indentLevel = para.getNumIlvl() != null ? para.getNumIlvl().intValue() : 0;String numFmt = para.getNumFmt(); // 獲取列表編號格式// 處理有序列表if ("decimal".equals(numFmt) || "upperRoman".equals(numFmt)) {StringBuilder prefixBuilder = new StringBuilder();for (int i = 0; i < indentLevel * 4; i++) {prefixBuilder.append(" ");}String prefix = prefixBuilder.toString();return prefix + ".";}// 處理無序列表else {String bullet;switch (para.getNumFmt()) {case "bullet":bullet = "?"; // 實心圓點break;default:bullet = "-"; // 默認用減號break;}StringBuilder prefixBuilder = new StringBuilder();for (int i = 0; i < indentLevel * 4; i++) {prefixBuilder.append(" ");}return prefixBuilder.toString() + bullet;}}private static boolean isListParagraph(XWPFParagraph paragraph) {return isOrderedList(paragraph) || isUnorderedList(paragraph); // 如果沒有找到對應的樣式,則不可能是列表段落}private static boolean isOrderedList(XWPFParagraph paragraph) {if (paragraph.getNumFmt() != null) {String numFmt = paragraph.getNumFmt();return "decimal".equals(numFmt) || "upperRoman".equals(numFmt) || "lowerRoman".equals(numFmt) ||"upperLetter".equals(numFmt) || "lowerLetter".equals(numFmt);}return false;}private static boolean isUnorderedList(XWPFParagraph paragraph) {if (paragraph.getNumFmt() != null) {String numFmt = paragraph.getNumFmt();return "bullet".equals(numFmt);}return false;}private static void processTable(XWPFTable table, FileWriter writer, String imageDir,List<String> imageNamePath) throws IOException {StringBuilder mdTable = new StringBuilder();List<XWPFTableRow> rows = table.getRows();for (int i = 0; i < rows.size(); i++) {XWPFTableRow row = rows.get(i);mdTable.append("|");// 處理每個單元格for (XWPFTableCell cell : row.getTableCells()) {StringBuilder cellContent = new StringBuilder();// 處理單元格內的段落for (XWPFParagraph para : cell.getParagraphs()) {cellContent.append(processParagraphContent(para, imageDir,imageNamePath).replace("\n", "<br>"));}mdTable.append(cellContent.toString().trim()).append("|");}mdTable.append("\n");// 添加表頭分隔線if (i == 0) {mdTable.append("|");for (int j = 0; j < row.getTableCells().size(); j++) {mdTable.append(" --- |");}mdTable.append("\n");}}writer.write(mdTable + "\n\n");}private static String processParagraphContent(XWPFParagraph paragraph, String imageDir,List<String> imageNamePath) throws IOException {StringBuilder sb = new StringBuilder();for (XWPFRun run : paragraph.getRuns()) {// 處理圖片for (XWPFPicture picture : run.getEmbeddedPictures()) {sb.append(saveImage(picture, imageDir,imageNamePath)).append(" ");}// 處理文本樣式String text = run.getText(0);if (text == null) continue;text = applyTextStyles(run, text);sb.append(text);}String content = sb.toString().trim();// 處理有序列表和無序列表if (isListParagraph(paragraph)) {String listMark = getListMark(paragraph);content ="* " + listMark + " " + content;}return content;}private static String applyTextStyles(XWPFRun run, String text) {if (run.isBold()) text = "**" + text + "**";if (run.isItalic()) text = "*" + text + "*";if (run.getUnderline() != UnderlinePatterns.NONE) text = "__" + text + "__";return text;}private static String saveImage(XWPFPicture picture, String imageDir,List<String> imageNamePath) throws IOException {XWPFPictureData picData = picture.getPictureData();String fileName = "img_" + UUID.randomUUID() + "." + picData.suggestFileExtension();File output = new File(imageDir, fileName);imageNamePath.add(output.getPath());try (FileOutputStream fos = new FileOutputStream(output)) {fos.write(picData.getData());}return "![" + fileName + "](" + imageDir + "/" + fileName + ")";}public static void main(String[] args) throws Exception {System.out.println(JSONObject.toJSONString( convertWordToMarkdown("word path")));}
}

獲得信息

{
"fileImagePathList":["文件中圖片路徑1","文件中圖片路徑2"],
"markdownContent": "markdwon 信息",
"mdPath": "markdown文件地址"
}

運行上方的程序將會得到
1、解析文件中所有圖片信息,保存到下方的地址
2、將word 文檔轉換成markdown
3、獲取markdown 文件

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/73796.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73796.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73796.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Axure設計之中繼器表格——拖動行排序教程(中繼器)

一、原理介紹 在Axure中實現表格行的拖動排序&#xff0c;主要依賴于中繼器的排序事件。然而要實現拖動效果&#xff0c;就必須結合動態面板&#xff0c;因為動態面板可以設置拖動事件&#xff0c;之所以使用動態面板或許是因為它可以更靈活地處理位置變化。用戶拖動行時&…

分布式渲染與云渲染:技術與應用的黃金搭檔

一、核心概念&#xff1a;先區分再關聯 分布式渲染是通過多臺設備并行計算拆分渲染任務的技術&#xff08;如將一幀拆分為 64 個小塊&#xff0c;64 臺電腦同時渲染&#xff09;&#xff1b; 云渲染是基于云計算的渲染服務&#xff0c;本質是分布式渲染的商業化落地—— 用戶無…

鼠標在客戶區內按下左鍵和雙擊右鍵

書籍&#xff1a;《Visual C 2017從入門到精通》的2.6鼠標 環境&#xff1a;visual studio 2022 內容&#xff1a;【例2.44】鼠標在客戶區內按下左鍵和雙擊右鍵 1.創建一個單文檔程序 一個簡單的單文檔程序-CSDN博客https://blog.csdn.net/qq_20725221/article/details/1463…

VMware虛擬機 ubuntu22.04無法與共享粘貼板和拖拽文件的解決方案

VMware虛擬機 ubuntu22.04無法與共享粘貼板和拖拉文件的解決方案 卸載VMware tools安裝open-vm-tools還無法拖拽文件 卸載VMware tools 確保卸載完vmware-tools # 進入vmware-tools安裝目錄/bin sudo vmware-uninstall-tools.pl sudo rm -rf /usr/lib/vmware-tools sudo apt-…

vue3 vue-router 傳遞路由參數

在 Vue 3 中&#xff0c;使用 vue-router 傳遞路由參數是非常常見的需求。 1. 使用動態路由參數&#xff08;params&#xff09; 動態路由參數是定義在路由規則中的占位符部分&#xff0c;例如 /user/:id。你可以通過 router.push 或 <router-link> 傳遞這些參數。 (1…

【Java SE】包裝類 Byte、Short、Integer、Long、Character、Float、Double、Boolean

參考筆記&#xff1a;java 包裝類 萬字詳解&#xff08;通俗易懂)_java包裝類-CSDN博客 目錄 1.簡介 2.包裝類的繼承關系圖 3.裝箱和拆箱 3.1 介紹 3.2 手動拆裝箱 3.3. 自動拆裝箱 ?4.關于String類型的轉化問題 4.1 String類型和基本類型的相互轉化 4.1.1 String —…

【Qt】QByteArray詳解

QByteArray 是 Qt 框架中用于處理原始字節數據的核心類&#xff0c;其實質可以概括為以下幾點&#xff1a; 1. 底層數據結構 ? 連續內存塊&#xff1a;存儲一段連續的字節數據&#xff08;char*&#xff09;&#xff0c;類似 std::vector<char>&#xff0c;但針對 Qt 框…

Stable Diffusion vue本地api接口對接,模型切換, ai功能集成開源項目 ollama-chat-ui-vue

1.開啟Stable Diffusion的api服務 編輯webui-user.bat 添加 –api 開啟api服務&#xff0c;然后保存啟動就可以了 2.api 文檔地址 http://127.0.0.1:7860/docs3. 文生圖 接口 地址 /sdapi/v1/txt2img //post 請求入參 {enable_hr: false, // 開啟高清hrdenoising_stre…

CentOS 7 部署RuoYi 項目

換源 備份現有的 YUM 源配置文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 默認的 CentOS 官方鏡像源替換為阿里云的鏡像源&#xff0c;以提高下載速度和穩定性。 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.co…

從 WPF 到 MAUI:跨平臺 UI 開發的進化之路

一、引言 在軟件開發領域&#xff0c;用戶界面&#xff08;UI&#xff09;開發一直是至關重要的環節。隨著技術的不斷發展&#xff0c;開發者對于創建跨平臺、高性能且美觀的 UI 需求日益增長。Windows Presentation Foundation&#xff08;WPF&#xff09;和 .NET Multi - pl…

C++ stack容器總結

stack 基本概念 概念&#xff1a; stack是一種后進先出(Last In First Out, LIFO)的數據結構&#xff0c;它只有一個出口 棧中只有頂端的元素才可以被外界使用&#xff0c;因此棧不允許有遍歷行為 棧中進入的數據稱為----入棧&#xff08;PUSH&#xff09; 棧中出去的數據成…

【SDMs分析1】基于ENMTools R包的生態位分化分析和圖像繪制(identity.test())

基于ENMTools包的生態位分化 1. 寫在前面2. 生態位分化檢驗案例13. 生態位分化檢驗案例21. 寫在前面 最近學了一個新的內容,主要是關于兩個物種之間生態位分化檢驗的 R 語言代碼。生態位分化是物種分布模型(SDM )研究中的關鍵部分,許多 SCI 論文都會涉及這一分析。該方法主…

SpringBoot 7 種實現 HTTP 調用的方式

1. HttpClient HttpClient是Apache基金會提供的一個用于發送HTTP請求的Java客戶端庫。 盡管它功能強大&#xff0c;但由于其API設計較為復雜且包體積龐大&#xff0c;在一些輕量級的應用場景中可能顯得過于臃腫。 不過&#xff0c;在需要高度定制化的HTTP請求時&#xff0c;H…

Ubuntu與Windows之間相互復制粘貼的方法

一、打開Ubuntu終端 二、卸載已有的工具 sudo apt-get autoremove open-vm-tools 三、安裝工具 sudo apt-get install open-vm-tools-desktop 四、重啟 直接輸入reboot 注&#xff1a;有任何問題歡迎評論區交流討論或者私信&#xff01;

ECharts實現數據可視化

ECharts實現數據可視化 一、Echarts的簡介二、Echarts使用教程1.下載echarts.min.js文件2.編寫echarts代碼&#xff08;1&#xff09;創建渲染實列&#xff08;2&#xff09;修改option達到預期的效果&#xff08;3&#xff09;創建配置項到實例中 三、Echarts的基礎配置四、前…

ArcGIS 10.8.1之后發布柵格數據的MapServer 動態工作空間 替換數據源渲染問題

背景 經過測試&#xff0c;Server 10.8.1、11.0、11.1發布相關服務設置動態空間之后&#xff0c;前端都無法自動讀取同名的clr色彩映射表文件進行渲染&#xff0c;服務都是由ArcGIS Pro進行發布。 原因 基于ArcMap發布的服務才支持&#xff0c;但是10.8.1之后不支持ArcMap發…

vscode在使用 alt + tab 切換程序窗口時,輸入法總是自動變為中文模式

因為需要在 vscode 中編寫代碼&#xff0c;將輸入法設為英文模式&#xff0c;但是用 alt tab 切換到瀏覽器查看文檔&#xff0c;此時瀏覽器也是英文模式&#xff0c;但是再切回 vscode 后就變為中文模式了&#xff0c;需要使用 shift 鍵切換為英文模式&#xff0c;一次兩次還好…

【Linux加餐-網絡命令】

一、Ping命令 Ping 是一種網絡工具&#xff0c;用于測試主機之間的連通性。它通過發送 ICMP&#xff08;Internet Control Message Protocol&#xff09;回顯請求 報文到目標主機&#xff0c;并等待目標主機返回 ICMP 回顯應答 報文&#xff0c;從而判斷網絡是否通暢以及測量往…

Maven工具學習使用(六)——聚合與繼承

Maven的聚合特性能夠把項目的各個模塊聚合在一起構建,而Maven的繼承特性則能幫助抽取個模塊相同的依賴和插件等配置,在簡化POM的同時,還能促進各個模塊配置的一致性。 一般說來一個項目的子模塊都應該使用同樣的groupId,如果他們一起開發和發布,還應該使用同樣的version,…

vulhub靶場jangow-01-1.0.1

啟動靶機時點shift停在這個界面 點e進入編輯頁面&#xff0c;把ro改成rw signie init/bin/bash Ctrlx保存&#xff0c;ip a查看網卡信息 vim /etc/network/interfaces 把enp0s17改為ens33&#xff0c;保存退出 重啟靶機&#xff0c;nmap掃ip ip為192.168.93.179 nmap掃端口 掃…