Java使用POI讀取office文件

很多時候我們只需要一份文件裏的部分信息,當文件量大的時候,一份一份的去找就很費時間了,java中使用poi可以實現對word、excel、ppt等文件的讀取,進而對文件內容進行操作

一、環境

  • eclipse(Version: 2019-03 (4.11.0))
  • jdk-12.0.1
  • poi-4.1.0

二、主要設計

  • 配置文件properties
  • 反射加載類
  • 正則表達式

三、導包

下載POI官方jar包:https://poi.apache.org/ ,由於沒找到相關的文檔說明,我是解壓後直接將所有的jar包複製到項目中

之前jar包沒完全導入,在對docx文檔讀取中使用XWPFWordExtractor extractor = new XWPFWordExtractor(xdoc);時一直顯示編譯時錯誤,點擊提示只顯示build path...百度了看了很多博客只看到有對excel文件操作時需要導入的包的解釋,所以我直接全部導入。。。(有知道的希望能留一下言,謝謝)——已解決,導包在文章底部

四、創建項目結構

對word文件的讀取:

  • read.office.Word爲抽象類,對應的實現類是Doc.java與Docx.java分別讀取.doc文件與.docx文件
  • read.test.Test類是對最終結果的運行測試
  • read.util.Util類是靜態方法的集合,包括加載配置文件等
  • office.properties配置文件,主要是在提取文件中需要的內容時用到了正則匹配,正則表達式是可變的,所以寫在了配置文件中,方便修改

五、源碼:

Doc.java

package read.office;

import java.io.File;
import java.io.FileInputStream;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class Doc extends Word {
	public String read(File file) {
		try (POIFSFileSystem fileSystem = new POIFSFileSystem(new FileInputStream(file));
				WordExtractor extractor = new WordExtractor(fileSystem);) {
			return extractor.getText();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}

Docx.java

package read.office;

import java.io.File;
import java.io.FileInputStream;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

public class Docx extends Word {
	public String read(File file) {
		try (XWPFDocument xdoc = new XWPFDocument(new FileInputStream(file));
				XWPFWordExtractor extractor = new XWPFWordExtractor(xdoc);) {
			return extractor.getText();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}

Util.java

package read.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Util {
	private static Properties properties;
	static {//加載配置文件
		InputStream url=Util.class.getClassLoader().getResourceAsStream("office.properties");
		properties=new Properties();
		try {
			properties.load(url);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(url!=null) {
				try {
					url.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	//截取目標字符串
	public static String subTargetText(String text,String regex) {
		Matcher matcher = Pattern.compile(regex).matcher(text);
		if(matcher.find()) {
			return matcher.group();
		}
		return null;
	}
	//根據文件名加載字符串匹配正則
	public static String getRegex(String fileName) {
		try {//查了資料,因爲配置文件默認是按ISO-8859-1進行讀取的,所以在如果想按照你想要的格式顯示就需要進行轉換
			String regex=new String(properties.getProperty(fileName).getBytes("ISO-8859-1"),"utf-8");
			return regex;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}

配置文件的默認讀取是編碼ISO-8859-1,哪怕你已經將項目中的所有文件的properties編碼屬性修改爲一致(如utf-8),在進行讀取中文的時候還是會出現亂碼的情況,所以需要進行轉換

Test.java

package read.test;

import java.io.File;
import read.office.Word;
import read.util.Util;

public class Test {
	public static void main(String[] args) {
		File dir = new File("E:\\大學\\1");
		run(dir);
	}

	// 根據文件的上一級目錄的File對象進行文件的遍歷
	public static void run(File dir) {
		File[] files = dir.listFiles();
		Word word = null;
		for (File file : files) {
			try {
				String fileName = file.getName();
				// 根據文件後綴反射獲取對應的類(因爲對類的命名是根據文件後綴類型命名的如Doc,Docx)
				String temp = fileName.substring(fileName.lastIndexOf(".") + 1);
				temp = temp.substring(0, 1).toUpperCase() + temp.substring(1).toLowerCase();
				word = (Word) Class.forName("read.office." + temp).getDeclaredConstructor().newInstance();
				String text = word.read(file);
				System.out.println(text);
				// 根據文件名獲加載配置文件裏的字符匹配正則
				temp = fileName.substring(0, fileName.lastIndexOf("."));
				System.out.println(fileName);
				String result = Util.subTargetText(text, Util.getRegex(temp));
				System.out.println(result);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

六、運行測試

讀取文件:文件1.與文件2內容相同

配置文件:要求:key與文件名相同,value爲要提取數據的正則表達式

運行結果:

測試成功!

七、可能遇到的問題

1、可能我們想要的內容在文檔中多處位置都有值,在以上的代碼中,只能返回第一個匹配正則表達式的值,而恰好第一個值並不是我們想要的。

原Util.java類中:只能獲取第一個值

	//截取目標字符串
	public static String subTargetText(String text,String regex) {
		Matcher matcher = Pattern.compile(regex).matcher(text);
		if(matcher.find()) {
			return matcher.group();
		}
		return null;
	}

修改後:可獲取所有的值,從中選擇需要的值

	List<String> list=new ArrayList<String>();
    //截取目標字符串
	public static List<String> subTargetText(String text,String regex) {
		Matcher matcher = Pattern.compile(regex).matcher(text);
		while(matcher.find()) {
			list.add(matcher.group());
		}
		return list;
	}

2、關於導包的問題

poi讀取word文件(doc、docx),需要導入的包爲:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章