java操作word文件通用工具類
阿新 • • 發佈:2019-01-01
package cn.com.test.util; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Enumeration; import java.util.Locale; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import org.apache.log4j.Logger; import freemarker.core.ParseException; import freemarker.template.Configuration; import freemarker.template.MalformedTemplateNameException; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateNotFoundException; /** * word工具類 * @author: Rodge * @time: 2017年12月24日 上午09:01:47 * @version:V1.0.0 */ public final class WordUtil { /** 日誌物件 **/ private static final Logger LOGGER = Logger.getLogger(WordUtil.class); /** 臨時目錄 **/ private static final String TEMP_PATH = "temp/"; /** 臨時docx檔案 **/ private static final String TEMP_FILE_DOCX = "temp.docx"; /** utf-8字元編碼 **/ private static final String CHARSET_UTF8 = "UTF-8"; /** 緩衝區大小1M **/ private static final int BUFFER_SIZE = 1024 * 1024; /** 私有構造器 **/ private WordUtil() { } /** * 根據模板生成新的word2003文件 * @param modelPath 模板存放路徑,例如:/template/word/word2003.xml * @param savePath 新文件儲存路徑,例如:D:/word/word2003.doc * @param map 寫入文件的資料 */ public static void createWord2003(String modelPath, String savePath, Map<String, Object> map) { Template template = getTemplate(modelPath); if (template != null) { File file = createFile(savePath); try (Writer out = new OutputStreamWriter(new FileOutputStream(file))) { template.process(map, out); } catch (TemplateException | IOException e) { LOGGER.error("生成word2003文件失敗", e); } } } /** * 根據模板生成新的word2003文件,以位元組陣列返回 * @param modelPath 模板存放路徑,例如:/template/word/word2003.xml * @param map 寫入文件的資料 * @return byte[] 位元組陣列 */ public static byte[] createWord2003(String modelPath, Map<String, Object> map) { Template template = getTemplate(modelPath); if (template != null) { return createNewTemp(template, map); } return new byte[0]; } /** * 根據模板生成新的word2007文件 * @param modelPathXml 模板存放路徑,例如:/template/word/word2007.xml * @param modelPathDocx 模板原文件,例如:/template/word/word2007.docx * @param savePath 新文件儲存路徑,例如:D:/word/word2007.docx * @param map 寫入文件的資料 */ public static void createWord2007(String modelPathXml, String modelPathDocx, String savePath, Map<String, Object> map) { ZipFile zipFile = null; ZipOutputStream zipOut = null; try { Template template = getTemplate(modelPathXml); byte[] bytes = createNewTemp(template, map); outTempFile(modelPathDocx); // 寫出臨時檔案(因Linux環境無法直接讀取modelPathDocx路徑) zipFile = new ZipFile(new File(TEMP_PATH + TEMP_FILE_DOCX)); // 讀取臨時檔案 Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries(); zipOut = new ZipOutputStream(new FileOutputStream(savePath)); int len = -1; byte[] buffer = new byte[BUFFER_SIZE]; while (zipEntrys.hasMoreElements()) { ZipEntry entry = zipEntrys.nextElement(); zipOut.putNextEntry(new ZipEntry(entry.toString())); if ("word/document.xml".equals(entry.toString())) { zipOut.write(bytes); } else { try (InputStream is = zipFile.getInputStream(entry)) { while ((len = is.read(buffer)) != -1) { zipOut.write(buffer, 0, len); } } catch (IOException e) { LOGGER.error("操作流失敗", e); } } } } catch (IOException e) { LOGGER.error("生成word2007文件失敗", e); } finally { if (zipFile != null) { try { zipFile.close(); } catch (IOException e) { LOGGER.error("關閉流失敗", e); } } if (zipOut != null) { try { zipOut.close(); } catch (IOException e) { LOGGER.error("關閉流失敗", e); } } deleteFiles(TEMP_PATH); // 刪除臨時檔案 } } /** * 根據模板生成新的word2007文件,以位元組陣列返回 * @param modelPathXml 模板存放路徑,例如:/template/word/word2007.xml * @param modelPathDocx 模板原文件,例如:/template/word/word2007.docx * @param map 寫入文件的資料 * @return byte[] */ public static byte[] createWord2007(String modelPathXml, String modelPathDocx, Map<String, Object> map) { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); ZipFile zipFile = null; ZipOutputStream zipOut = null; try { Template template = getTemplate(modelPathXml); byte[] bytes = createNewTemp(template, map); outTempFile(modelPathDocx); // 寫出臨時檔案(因Linux環境無法直接讀取modelPathDocx路徑) zipFile = new ZipFile(new File(TEMP_PATH + TEMP_FILE_DOCX)); // 讀取臨時檔案 Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries(); zipOut = new ZipOutputStream(byteStream); int len = -1; byte[] buffer = new byte[BUFFER_SIZE]; while (zipEntrys.hasMoreElements()) { ZipEntry entry = zipEntrys.nextElement(); zipOut.putNextEntry(new ZipEntry(entry.toString())); if ("word/document.xml".equals(entry.toString())) { zipOut.write(bytes); } else { try (InputStream is = zipFile.getInputStream(entry)) { while ((len = is.read(buffer)) != -1) { zipOut.write(buffer, 0, len); } } catch (IOException e) { LOGGER.error("操作流失敗", e); } } } } catch (IOException e) { LOGGER.error("生成word2007文件失敗", e); } finally { if (zipFile != null) { try { zipFile.close(); } catch (IOException e) { LOGGER.error("關閉流失敗", e); } } if (zipOut != null) { try { zipOut.close(); } catch (IOException e) { LOGGER.error("關閉流失敗", e); } } deleteFiles(TEMP_PATH); // 刪除臨時檔案 } return byteStream.toByteArray(); } /** * 寫出臨時檔案 * @param modelPathDocx word2007原文件存放路徑 */ private static void outTempFile(String modelPathDocx) { InputStream input = WordUtil.class.getClassLoader().getResourceAsStream(modelPathDocx); if (input != null) { try (FileOutputStream fos = new FileOutputStream(createFile(TEMP_PATH + TEMP_FILE_DOCX))) { int len = -1; byte[] buffer = new byte[BUFFER_SIZE]; while ((len = input.read(buffer)) != -1) { fos.write(buffer, 0, len); } } catch (IOException e) { LOGGER.error("寫出臨時檔案失敗", e); } finally { try { input.close(); } catch (IOException e) { LOGGER.error("關閉輸入流失敗", e); } } } } /** * 刪除該目錄下所有檔案 * @param filePath 檔案目錄路徑,如:d:/test/ */ public static boolean deleteFiles(String filePath) { File file = new File(filePath); if (file.exists()) { File[] files = file.listFiles(); if (files != null && files.length > 0) { for (File f : files) { if (f.isFile() && f.delete()) { LOGGER.info("刪除" + f.getName() + "檔案成功"); } } return true; } } return false; } /** * 刪除單個檔案 * @param filePath 檔案目錄路徑,如:d:/test/ * @param fileName 檔名稱,如:110.doc */ public static boolean deleteFile(String filePath, String fileName) { File file = new File(filePath); if (file.exists()) { File[] files = file.listFiles(); if (files != null && files.length > 0) { for (File f : files) { if (f.isFile() && f.getName().equals(fileName)) { return f.delete(); } } } } return false; } /** * 寫入資料,生成新的模板檔案以位元組陣列返回 * @param template 模板物件 * @param map 寫入文件的資料 * @return byte[] */ private static byte[] createNewTemp(Template template, Map<String, Object> map) { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); try (Writer out = new OutputStreamWriter(byteStream)) { template.process(map, out); } catch (TemplateException | IOException e) { LOGGER.error("生成新模板檔案失敗", e); } return byteStream.toByteArray(); } /** * 建立檔案物件 * @param filePath 檔案路徑,例如:temp/test.doc * @return File */ private static File createFile(String filePath) { File file = null; try { // 建立檔案目錄 file = new File(filePath.substring(0, filePath.lastIndexOf('/'))); if (!file.exists()) { file.mkdirs(); } // 建立檔案物件 file = new File(filePath); if (!file.exists() && file.createNewFile()) { LOGGER.info("建立檔案物件成功"); } } catch (IOException e) { LOGGER.error("建立檔案物件失敗", e); } return file; } /** * 獲取模板物件 * @param modelPath 模板存放路徑 * @return */ private static Template getTemplate(String modelPath) { Template template = null; try { Configuration configuration = new Configuration(Configuration.VERSION_2_3_25); configuration.setEncoding(Locale.getDefault(), CHARSET_UTF8); configuration.setClassForTemplateLoading(WordUtil.class, modelPath.substring(0, modelPath.lastIndexOf('/'))); template = configuration.getTemplate(modelPath.substring(modelPath.lastIndexOf('/') + 1)); } catch (TemplateNotFoundException | MalformedTemplateNameException | ParseException e) { LOGGER.error("讀取模板失敗", e); } catch (IOException e) { LOGGER.error("建立模板物件失敗", e); } return template; } }