JAVA 实现DOC到DOCX转换(实用篇)

该文章已生成可运行项目,

注意1:本文使用了apache的老版本依赖,请斟酌后引用
注意2:这个方法会导致doc文档的表格&图片内容丢失

一:依赖

小工具引入的依赖如下(老版本)

        <!-- POI 核心 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

        <!-- HWPF (Word 97-2003) 支持 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.17</version>
        </dependency>

        <!-- XWPF (Word 2007+) 支持 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

二:正文

依赖不需要过多介绍,直接看代码

1.带上导入的依赖结构是为了让代码可以直接使用,小伙伴们直接cv即可
2.该方法使用 MultipartFile 作为传入传出对象,主要是业务需要,也可以改为流式传输,本文不介绍其他方式

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.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;



public class DocToDocxUtil {

	public static MultipartFile convert(MultipartFile originalFile) throws IOException {
		// 参数校验
		Objects.requireNonNull(originalFile, "Original file cannot be null");

		if (originalFile.isEmpty()) {
			throw new IllegalArgumentException("The provided file is empty.");
		}

		String originalFilename = originalFile.getOriginalFilename();
		if (originalFilename == null) {
			throw new IllegalArgumentException("Original filename cannot be null.");
		}

		if (!originalFilename.toLowerCase().endsWith(".doc")) {
			throw new IllegalArgumentException("The file must have a .doc extension. Received: " + originalFilename);
		}

		HWPFDocument hwpfDocument = null;
		XWPFDocument xwpfDocument = null;
		InputStream inputStream = null;
		ByteArrayOutputStream baos = null;

		try {
			inputStream = originalFile.getInputStream();
			hwpfDocument = new HWPFDocument(inputStream);
			xwpfDocument = new XWPFDocument();
			baos = new ByteArrayOutputStream();

			// 获取文档范围并处理内容
			Range range = hwpfDocument.getRange();
			int paragraphCount = range.numParagraphs();

			// 复制段落内容
			for (int i = 0; i < paragraphCount; i++) {
				Paragraph paragraph = range.getParagraph(i);
				String text = paragraph.text();

				// 清理文本
				text = cleanDocText(text);

				if (!text.isEmpty()) {
					XWPFParagraph xwpfParagraph = xwpfDocument.createParagraph();
					XWPFRun xwpfRun = xwpfParagraph.createRun();
					xwpfRun.setText(text);
				}
			}

			// 写入输出流
			xwpfDocument.write(baos);
			byte[] docxBytes = baos.toByteArray();

			// 创建新的MultipartFile
			return createMultipartFile(originalFile, originalFilename, docxBytes);

		} catch (Exception e) {
			throw new IOException("Failed to convert DOC to DOCX: " + e.getMessage(), e);
		} finally {
			// 手动关闭资源(3.17可能不支持try-with-resources)
			closeQuietly(hwpfDocument);
			closeQuietly(xwpfDocument);
			closeQuietly(inputStream);
			closeQuietly(baos);
		}
	}

	private static String cleanDocText(String text) {
		if (text == null || text.isEmpty()) {
			return "";
		}

		String cleaned = text.trim();

		if (cleaned.endsWith("\r")) {
			cleaned = cleaned.substring(0, cleaned.length() - 1);
		} else if (cleaned.endsWith("\r\n")) {
			cleaned = cleaned.substring(0, cleaned.length() - 2);
		} else if (cleaned.endsWith("\n")) {
			cleaned = cleaned.substring(0, cleaned.length() - 1);
		}

		return cleaned;
	}

	private static MultipartFile createMultipartFile(MultipartFile originalFile,
													 String originalFilename,
													 byte[] content) {

		String newFilename = originalFilename.replaceAll("(?i)\\.doc$", ".docx");

		ByteArrayResource resource = new ByteArrayResource(content) {
			@Override
			public String getFilename() {
				return newFilename;
			}
		};

		return new MultipartFile() {
			@Override
			public String getName() {
				return originalFile.getName();
			}

			@Override
			public String getOriginalFilename() {
				return newFilename;
			}

			@Override
			public String getContentType() {
				return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
			}

			@Override
			public boolean isEmpty() {
				return content.length == 0;
			}

			@Override
			public long getSize() {
				return content.length;
			}

			@Override
			public byte[] getBytes() {
				return content;
			}

			@Override
			public InputStream getInputStream() {
				return new ByteArrayInputStream(content);
			}

			@Override
			public void transferTo(java.io.File dest) throws IOException {
				try (InputStream is = getInputStream();
					 java.io.FileOutputStream fos = new java.io.FileOutputStream(dest)) {
					byte[] buffer = new byte[8192];
					int bytesRead;
					while ((bytesRead = is.read(buffer)) != -1) {
						fos.write(buffer, 0, bytesRead);
					}
				}
			}
		};
	}

	private static void closeQuietly(AutoCloseable closeable) {
		if (closeable != null) {
			try {
				closeable.close();
			} catch (Exception e) {
				// 安静关闭,忽略异常
			}
		}
	}

本文章已经生成可运行项目
### 将 Java 文档 (Javadoc) 转换为 .docx 格式的解决方案 为了将 Javadoc 文件转换成 Word 的 `.docx` 格式,可以采用多种方法和技术栈来完成这一目标。一种常见的做法是先通过工具生成 HTML 或 XML 形式的 javadoc,再利用第三方库将其化为 DOCX。 对于直接处理 DocDocx 之间的转换,在 Java 中可以通过 Apache POI 库操作 Office 文档[^1]。然而针对 javadoc 特殊情况,则可能需要额外步骤: - 使用 `javadoc` 命令行工具导出项目 API 文档至 HTML; - 利用开源软件如 Pandoc 进行格式间的变;或者编写自定义解析器读取并重组数据结构最终保存为目标文件类型。 下面给出一段基于上述思路的简单示例代码片段用于说明如何借助外部命令调用来实现此功能的一部分逻辑: ```java import java.io.*; public class JavadocToDocx { public static void main(String[] args){ try{ // 执行javac编译指令生成html版api文档 Process process = Runtime.getRuntime().exec("javadoc -d output_html src/*.java"); int exitVal = process.waitFor(); File dir = new File("output_html"); String inputPath=dir.getAbsolutePath(); // 构建pandoc执行路径及参数列表 List<String> commandList=new ArrayList<>(); commandList.add("pandoc"); commandList.addAll(Arrays.asList("-s",inputPath,"-o","output.docx")); // 启动子进程运行Pandoc进行HTML到DOCX转换 ProcessBuilder pb =new ProcessBuilder(commandList); Process p2 =pb.start(); BufferedReader br = new BufferedReader(new InputStreamReader(p2.getInputStream())); while(br.readLine()!=null){} System.out.println("Conversion completed."); }catch(Exception e){ e.printStackTrace(); } } } ``` 需要注意的是这段程序仅作为概念验证用途,并未考虑实际应用中的诸多细节问题比如错误处理机制、跨平台兼容性以及性能优化等方面的内容。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值