java如何替换word/doc文件中的内容

 更新时间:2023年06月30日 08:43:59   作者:五官一体即忢  
docx格式的文件本质上是一个XML文件,只要用占位符在指定的地方标记,然后替换掉标记出的内容,这篇文章主要介绍了java替换word/doc文件中的内容,需要的朋友可以参考下

docx格式的文件本质上是一个XML文件,只要用占位符在指定的地方标记,然后替换掉标记出的内容,就能达到我们的目的

封装成工具类

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
 * Author ht
 * Date: 2023-06-30
 */
//替换.docx文件的工具类
public class DocxUtil {
    //    保存随机生的解压出.docx文件的保存目录
    private static final String cachePath = System.getProperty("user.dir") + File.separator + UUID.randomUUID().toString().replaceAll("-", "");
    //    保存模板文件的输入流和模板压缩输入流
    private static final List<InputStream> iss = new ArrayList<>();
    //    替换docx文件中的内容
    public static void compile(FileInputStream is, Map<String, String> data, FileOutputStream os) throws IOException {
//        获取模板保存的目录
        Path path = Paths.get(cachePath);
//        如果不存在或者当前的模板输入流不在输入流集合中就解压模板
        if (!Files.exists(path) || !iss.contains(is)) {
//        解压docx文件
            unDocx(is);
        }
//        替换document.xml的内容
        replaceXmlContent(data);
//        把解压的文件重新压缩成docx文件
        buildDocx(os);
    }
    //    解压docx文件
    private static void unDocx(FileInputStream template) throws IOException {
//        解压出来文件保存的目录
        File cacheDir = new File(cachePath);
        if (!cacheDir.exists()) {
//            不存在就先创建该文件夹
            Files.createDirectory(Paths.get(cacheDir.getPath()));
        }
//        创建压缩包输入流
        ZipInputStream zis = new ZipInputStream(template);
//        把需要关闭的模板输入流存到集合中
        iss.add(template);
        iss.add(zis);
//        获取首个压缩文件中的文件
        ZipEntry entry = zis.getNextEntry();
//        内容缓冲区
        byte[] buff = new byte[1024 * 10];
//        循环获取压缩包中的压缩文件
        while (entry != null) {
//            判断当前的压缩文件是文件夹还是文件
            if (entry.isDirectory()) {
//                如果是文件夹就要创建对应的文件夹
                Path tempDir = Paths.get(cacheDir.getPath() + File.separator + entry.getName());
//                不存在就创建
                if (!Files.exists(tempDir)) {
                    Files.createDirectory(tempDir);
                }
            } else {
//                如果是文件就创建文件写入内容
                File file = new File(cacheDir, entry.getName());
//                创建文件的输出流
                FileOutputStream fos = new FileOutputStream(file);
//                写入内容到输出流
                int len;
                while ((len = zis.read(buff)) != -1) {
                    fos.write(buff, 0, len);
                }
//                zis.transferTo(fos); // jdk9及更高版本可以用这个
//                关闭当前文件的输出流
                fos.close();
            }
//            获取下一个压缩文件
            entry = zis.getNextEntry();
        }
        System.out.println("===== 模板docx文件解压完成 =====");
    }
    //    替换document.xml的内容
    private static void replaceXmlContent(Map<String, String> data) throws IOException {
//        document.xml的位置
        String documentXmlPath = cachePath + File.separator + "word" + File.separator + "document.xml";
//        获取document.xml文件的输入流
        FileInputStream fis = new FileInputStream(documentXmlPath);
//        读取xml中的内容
        byte[] buff = new byte[fis.available()];
        fis.read(buff);
//        获取xml文件中的内容
        String content = new String(buff);
//        拿到Map集合中的数据和值,替换掉对应位置的内容
        for (String key : data.keySet()) {
            String value = data.get(key);
            System.out.println("替换 [ {{" + key + "}} ] 为 => [ " + value + " ]");
            content = content.replaceAll("\\{\\{" + key + "\\}\\}", value);
        }
//        把替换好的内容写入原来的document.xml文件中
        FileOutputStream fos = new FileOutputStream(documentXmlPath);
//        写入内容
        fos.write(content.getBytes(StandardCharsets.UTF_8));
//        关闭流
        fos.close();
        fis.close();
        System.out.println("===== 替换完成 =====");
    }
    //    把替换好document.xml内容的文件夹重新压缩成docx文件
    private static void buildDocx(FileOutputStream template) throws IOException {
//        创建压缩文件输出流
        ZipOutputStream zos = new ZipOutputStream(new DataOutputStream(template));
//        获取要压缩文件的路径
        Path path = Paths.get(cachePath);
//        遍历当前压缩文件路径下的所有文件
        Files.walkFileTree(path, new SimpleFileVisitor<>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
//                获取当前文件的父目录的名字
                String parent = file.getParent().getFileName().toString();
//                压缩文件的名字
                String zipFileName;
//                如果父目录是根目录名字就是当前的名字否则就是夫目录加上当前的名字
                if (parent.equals(path.toFile().getName())) {
                    zipFileName = file.toFile().getName();
                } else {
//                    如果父目录的夫目录是word就需要word+当前文件的父目录+当前文件的名字
                    if ("word".equals(file.getParent().getParent().toFile().getName())) {
                        zipFileName = "word" + File.separator + parent + File.separator + file.toFile().getName();
                    } else {
//                        如果不是就是当前文件的父目录+当前文件的名字
                        zipFileName = parent + File.separator + file.toFile().getName();
                    }
                }
//                把文件添加到压缩包中
                zos.putNextEntry(new ZipEntry(zipFileName));
//                获取当前文件的输入流
                DataInputStream zis = new DataInputStream(new FileInputStream(file.toFile()));
//                写入内容到当前的压缩文件
                int len;
                byte[] buff = new byte[1024 * 10];
                while ((len = zis.read(buff)) != -1) {
                    zos.write(buff, 0, len);
                }
                zis.close();
//                zis.transferTo(zos); // jdk9及更高版本可以用这个
                return super.visitFile(file, attrs);
            }
        });
//        关闭流
        zos.close();
        template.close();
        System.out.println("===== 把解压的文件重新压缩成.docx ====");
    }
    //    关闭模板输入流和清除缓存文件
    public static void closeTemplateAndClearCache() {
//        关闭集合中的所有流
        for (InputStream inputStream : iss) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //            删除缓存文件
        deleteCache(new File(cachePath));
        System.out.println("===== 关闭了模板,清理了缓存 =====");
    }
    //    删除不用的缓存解压文件目录
    private static void deleteCache(File cachePath) {
//        先删文件夹里面的文件
        for (File file : Objects.requireNonNull(cachePath.listFiles())) {
//            是文件夹就递归调用
            if (file.isDirectory()) {
                deleteCache(file);
            } else {
//                是文件就直接删
                file.delete();
            }
        }
//        删掉自己
        cachePath.delete();
    }
}

使用

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
 * Author ht
 * Date: 2023-06-30
 */
public class App {
    public static void main(String[] args) throws IOException {
//        填充的数据
        Map<String, String> data = new HashMap<>();
        data.put("name", "hello world");
        data.put("time", "2022年10月1日");
//        模板输入流
        FileInputStream is = new FileInputStream("src/main/resources/one.docx");
//        模板输出流
        FileOutputStream os = new FileOutputStream("src/main/resources/test1.docx");
        FileOutputStream os1 = new FileOutputStream("src/main/resources/test2.docx");
//        生成模板
        DocxUtil.compile(is, data, os);
        DocxUtil.compile(is, data, os1);
        //    关闭模板输入流和清除缓存文件
        DocxUtil.closeTemplateAndClearCache();
    }
}

记录一些代码和问题处理方式,需要参考的请谨慎。

到此这篇关于java如何替换word/doc文件中的内容的文章就介绍到这了,更多相关java替换文件内容内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的FileWriter用法详解与实战记录

    Java中的FileWriter用法详解与实战记录

    这篇文章主要给大家介绍了关于Java中FileWriter用法的相关资料,包括写入字符数据到文件、字符数组和部分字符写入、配合BufferedWriter使用等方法,同时也解释了其与OutputStreamWriter,BufferedWriter的异同特性,适合简单的文件写入操作,需要的朋友可以参考下
    2024-10-10
  • 如何在Java中使用标准库创建临时文件

    如何在Java中使用标准库创建临时文件

    有时候我们程序运行时需要产生中间文件,但是这些文件只是临时用途,并不做长久保存,我们可以使用临时文件,不需要长久保存,这篇文章主要给大家介绍了关于如何在Java中使用标准库创建临时文件的相关资料,需要的朋友可以参考下
    2023-10-10
  • java模拟post请求登录猫扑示例分享

    java模拟post请求登录猫扑示例分享

    这篇文章主要介绍了java模拟post请求登录猫扑的小示例,需要的朋友可以参考下
    2014-02-02
  • MyBatis-Plus3.x版本使用入门和踩过的坑

    MyBatis-Plus3.x版本使用入门和踩过的坑

    Mybatis-Plus是Mybatis的增强版,他只是在Mybatis的基础上增加了功能,且并未对原有功能进行任何的改动,本文给大家说一下MyBatis-Plus3.x版本使用入门和踩过的坑,感兴趣的朋友跟随小编一起看看吧
    2023-10-10
  • Java批量导出word压缩后的zip文件案例

    Java批量导出word压缩后的zip文件案例

    这篇文章主要介绍了Java批量导出word压缩后的zip文件案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • Spring Boot项目中Maven编译参数source、target与release的区别及配置实践方案

    Spring Boot项目中Maven编译参数source、target与release的区别及配置实践方案

    在Spring Boot项目开发中,将本地代码打包部署到服务器时,常会遇到UnsupportedClassVersionError或NoSuchMethodError等异常,本文将直观解析这些配置的区别,并提供标准的配置方案,感兴趣的朋友跟随小编一起看看吧
    2026-02-02
  • SpringBoot Session接口验证实现流程详解

    SpringBoot Session接口验证实现流程详解

    这篇文章主要介绍了SpringBoot+Session实现接口验证(过滤器+拦截器)文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-09-09
  • JpaRepository 实现简单条件查询

    JpaRepository 实现简单条件查询

    这篇文章主要介绍了JpaRepository 实现简单条件查询,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • spring cloud oauth2 feign 遇到的坑及解决

    spring cloud oauth2 feign 遇到的坑及解决

    这篇文章主要介绍了spring cloud oauth2 feign 遇到的坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 详解SpringBoot项目整合Vue做一个完整的用户注册功能

    详解SpringBoot项目整合Vue做一个完整的用户注册功能

    本文主要介绍了SpringBoot项目整合Vue做一个完整的用户注册功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07

最新评论