首页 > 编程语言 > 详细

用java语言通过POI实现word文档的按标题提取

时间:2019-03-20 23:06:32      阅读:167      评论:0      收藏:0      [点我收藏+]

最近有一个项目需要将一个word文档中的数据提取到数据库中。就去网上查了好多资料,最靠谱的就是用poi实现word文档的提取。

喝水不忘挖井人,我查了好多资料就这个最靠谱,我的这篇博客主要是借鉴https://blog.csdn.net/qq_16601953/article/details/82415518

 

现在讲一下思路:

1.首先我们要用poi将word中的数据提取出来,我把提取的数据存到字符数组中,

2.然后通过sql数据将字符串数组中的数据存到mysql数据库中

当然需要jar包依赖

技术分享图片

可能不需要这么多,但是我都导进去了

网上有poi的下载链接http://120.52.51.14/archive.apache.org/dist/poi/release/bin/poi-bin-3.17-20170915.zip

如果实在找不到的话加我q2206996799     2019年4月1日之前我应该还有

下面贴上主要代码我是按照上面博客借鉴的稍微根据我的需求改了改

  1 import java.io.FileInputStream;
  2 import java.io.FileOutputStream;
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.io.OutputStream;
  6 import java.math.BigInteger;
  7 import java.util.HashMap;
  8 import java.util.List;
  9 import java.util.Map;
 10 
 11 import org.apache.poi.xwpf.usermodel.XWPFDocument;
 12 import org.apache.poi.xwpf.usermodel.XWPFParagraph;
 13 import org.apache.poi.xwpf.usermodel.XWPFRun;
 14 import org.apache.poi.xwpf.usermodel.XWPFStyle;
 15 import org.apache.poi.xwpf.usermodel.XWPFStyles;
 16 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
 17 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff;
 18 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
 19 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString;
 20 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
 21 import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType;
 22 
 23 
 24 public class test {
 25 private static Map<String,Map<String,Object>> orderMap =new HashMap<String, Map<String,Object>>();
 26 
 27     public void init(String targetPath,String sourcePath){
 28         InputStream is = null;
 29         XWPFDocument doc=null;
 30         OutputStream out=null;
 31         try {
 32             XWPFDocument createDoc = new XWPFDocument();
 33 
 34             is = new FileInputStream(sourcePath);
 35             doc = new XWPFDocument(is);
 36             //获取段落
 37             List<XWPFParagraph> paras=doc.getParagraphs();
 38 
 39             for (XWPFParagraph para : paras){
 40  //             System.out.println(para.getCTP());//得到xml格式
 41               System.out.println(para.getStyleID());//段落级别
 42               System.out.println(para.getParagraphText());//段落内容
 43 
 44                 String titleLvl = getTitleLvl(doc,para);//获取段落级别
 45                 if("a5".equals(titleLvl)||"HTML".equals(titleLvl)||"".equals(titleLvl)||null==titleLvl){
 46                     titleLvl = "8";
 47                 }
 48               System.out.println(titleLvl+"-----");//0,1,2
 49                 if(!"8".equals(titleLvl)){
 50                     System.out.println(titleLvl+"===="+para.getParagraphText());
 51                 }
 52 
 53 
 54                 XWPFParagraph ctPara = createDoc.createParagraph();
 55                 //一个XWPFRun代表具有相同属性的一个区域。
 56                 XWPFRun ctRun = ctPara.createRun();
 57                 String ctText = para.getParagraphText();
 58                 ctRun.setFontFamily("宋体");//字体
 59                 ctRun.setFontSize(12);
 60 
 61                 if(null!=titleLvl&&!"".equals(titleLvl)&&!"8".equals(titleLvl)){
 62                     addCustomHeadingStyle(createDoc,titleLvl,Integer.parseInt(titleLvl));
 63                     String orderCode = getOrderCode(titleLvl);//获取编号
 64                     ctText = orderCode+" "+ctText;
 65                     ctRun.setBold(true);//标题加粗
 66                     ctRun.setFontSize(14);
 67 
 68                     ctPara.setStyle(titleLvl);
 69 
 70                 }else{//正文
 71                     ctPara.setIndentationFirstLine(567);//首行缩进:567==1厘米
 72 //                  ctRun.setTextPosition(6);//设置行间距
 73                 }
 74 
 75                 ctRun.setText(ctText);//内容
 76             }
 77             out=new FileOutputStream(targetPath);
 78             createDoc.write(out);
 79         } catch (Exception e) {
 80             e.printStackTrace();
 81         } finally{
 82             try {
 83                 if(null!=out){
 84                     out.close();
 85                 } 
 86                 if(null!=is){
 87                     is.close();
 88                 }
 89             }catch (IOException e) {
 90                 e.printStackTrace();
 91             }
 92         }
 93     }
 94 
 95     /**
 96      * Word中的大纲级别,可以通过getPPr().getOutlineLvl()直接提取,但需要注意,Word中段落级别,通过如下三种方式定义: 
 97      *  1、直接对段落进行定义; 
 98      *  2、对段落的样式进行定义; 
 99      *  3、对段落样式的基础样式进行定义。 
100      *  因此,在通过“getPPr().getOutlineLvl()”提取时,需要依次在如上三处读取。
101      * @param doc
102      * @param para
103      * @return
104      */
105     private static String getTitleLvl(XWPFDocument doc, XWPFParagraph para) {
106         String titleLvl = "";
107         try {
108             //判断该段落是否设置了大纲级别
109             if (para.getCTP().getPPr().getOutlineLvl() != null) {
110                 // System.out.println("getCTP()");
111 //              System.out.println(para.getParagraphText());
112 //              System.out.println(para.getCTP().getPPr().getOutlineLvl().getVal());
113 
114                 return String.valueOf(para.getCTP().getPPr().getOutlineLvl().getVal());
115             }
116         } catch (Exception e) {
117 
118         }
119 
120         try {
121             //判断该段落的样式是否设置了大纲级别
122             if (doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl() != null) {
123 
124                 // System.out.println("getStyle");
125 //              System.out.println(para.getParagraphText());
126 //              System.out.println(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl().getVal());
127 
128                 return String.valueOf(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getPPr().getOutlineLvl().getVal());
129             }
130         } catch (Exception e) {
131 
132         }
133 
134         try {
135             //判断该段落的样式的基础样式是否设置了大纲级别
136             if (doc.getStyles().getStyle(doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal())
137                     .getCTStyle().getPPr().getOutlineLvl() != null) {
138                 // System.out.println("getBasedOn");
139 //              System.out.println(para.getParagraphText());
140                 String styleName = doc.getStyles().getStyle(para.getStyle()).getCTStyle().getBasedOn().getVal();
141 //              System.out.println(doc.getStyles().getStyle(styleName).getCTStyle().getPPr().getOutlineLvl().getVal());
142 
143                 return String.valueOf(doc.getStyles().getStyle(styleName).getCTStyle().getPPr().getOutlineLvl().getVal());
144             }
145         } catch (Exception e) {
146 
147         }
148 
149         try {
150             if(para.getStyleID()!=null){
151                 return para.getStyleID();
152             }
153         } catch (Exception e) {
154 
155         }
156 
157         return titleLvl;
158     }
159 
160     /**
161      * 增加自定义标题样式。这里用的是stackoverflow的源码
162      * 
163      * @param docxDocument 目标文档
164      * @param strStyleId 样式名称
165      * @param headingLevel 样式级别
166      */
167     private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {
168 
169         strStyleId = String.valueOf(Integer.parseInt(strStyleId)+1);
170         CTStyle ctStyle = CTStyle.Factory.newInstance();
171         ctStyle.setStyleId(strStyleId);
172 
173         CTString styleName = CTString.Factory.newInstance();
174         styleName.setVal(strStyleId);
175         ctStyle.setName(styleName);
176 
177         CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
178         indentNumber.setVal(BigInteger.valueOf(headingLevel));
179 
180         // lower number > style is more prominent in the formats bar
181         ctStyle.setUiPriority(indentNumber);
182 
183         CTOnOff onoffnull = CTOnOff.Factory.newInstance();
184         ctStyle.setUnhideWhenUsed(onoffnull);
185 
186         // style shows up in the formats bar
187         ctStyle.setQFormat(onoffnull);
188 
189         // style defines a heading of the given level
190         CTPPr ppr = CTPPr.Factory.newInstance();
191         ppr.setOutlineLvl(indentNumber);
192         ctStyle.setPPr(ppr);
193 
194         XWPFStyle style = new XWPFStyle(ctStyle);
195 
196         // is a null op if already defined
197         XWPFStyles styles = docxDocument.createStyles();
198 
199         style.setType(STStyleType.PARAGRAPH);
200         styles.addStyle(style);
201 
202     }
203     /**
204      * 获取标题编号
205      * @param titleLvl
206      * @return
207      */
208     private static String getOrderCode(String titleLvl) {
209         String order = "";
210 
211         if("0".equals(titleLvl)||Integer.parseInt(titleLvl)==8){//文档标题||正文
212             return "";
213         }else if(Integer.parseInt(titleLvl)>0&&Integer.parseInt(titleLvl)<8){//段落标题
214 
215             //设置最高级别标题
216             Map<String,Object> maxTitleMap = orderMap.get("maxTitleLvlMap");
217             if(null==maxTitleMap){//没有,表示第一次进来
218                 //最高级别标题赋值
219                 maxTitleMap = new HashMap<String, Object>();
220                 maxTitleMap.put("lvl", titleLvl);
221                 orderMap.put("maxTitleLvlMap", maxTitleMap);
222             }else{
223                 String maxTitleLvl = maxTitleMap.get("lvl")+"";//最上层标题级别(0,1,2,3)
224                 if(Integer.parseInt(titleLvl)<Integer.parseInt(maxTitleLvl)){//当前标题级别更高
225                     maxTitleMap.put("lvl", titleLvl);//设置最高级别标题
226                     orderMap.put("maxTitleLvlMap", maxTitleMap);
227                 }
228             }
229 
230             //查父节点标题
231             int parentTitleLvl = Integer.parseInt(titleLvl)-1;//父节点标题级别
232             Map<String,Object> cMap = orderMap.get(titleLvl);//当前节点信息
233             Map<String,Object> pMap = orderMap.get(parentTitleLvl+"");//父节点信息
234 
235             if(0==parentTitleLvl){//父节点为文档标题,表明当前节点为1级标题
236                 int count= 0;
237                 //最上层标题,没有父节点信息
238                 if(null==cMap){//没有当前节点信息
239                     cMap = new HashMap<String, Object>();
240                 }else{
241                     count = Integer.parseInt(String.valueOf(cMap.get("cCount")));//当前序个数
242                 }
243                 count++;
244                 order = count+"";
245                 cMap.put("cOrder", order);//当前序
246                 cMap.put("cCount", count);//当前序个数
247                 orderMap.put(titleLvl, cMap);
248 
249             }else{//父节点为非文档标题
250                 int count= 0;
251                 //如果没有相邻的父节点信息,当前标题级别自动升级
252                 if(null==pMap){
253                     return getOrderCode(String.valueOf(parentTitleLvl));
254                 }else{
255                     String pOrder = String.valueOf(pMap.get("cOrder"));//父节点序
256                     if(null==cMap){//没有当前节点信息
257                         cMap = new HashMap<String, Object>();
258                     }else{
259                         count = Integer.parseInt(String.valueOf(cMap.get("cCount")));//当前序个数
260                     }
261                     count++;
262                     order = pOrder+"."+count;//当前序编号
263                     cMap.put("cOrder", order);//当前序
264                     cMap.put("cCount", count);//当前序个数
265                     orderMap.put(titleLvl, cMap);
266                 }
267             }
268 
269             //字节点标题计数清零
270             int childTitleLvl = Integer.parseInt(titleLvl)+1;//子节点标题级别
271             Map<String,Object> cdMap = orderMap.get(childTitleLvl+"");//
272             if(null!=cdMap){
273                 cdMap.put("cCount", 0);//子节点序个数
274                 orderMap.get(childTitleLvl+"").put("cCount", 0);
275             }
276         }
277         return order;
278     }
279 
280     public static void main(String[] args) {
281         InputStream is = null;
282         XWPFDocument doc=null;
283         OutputStream out=null;
284         String[] title= new String [276];
285         String[] concent= new String [276];
286         String[] type= new String [276];
287         int i=0;
288         try {
289             XWPFDocument createDoc = new XWPFDocument();
290 
291             is = new FileInputStream("E:/doc/a.docx");
292             doc = new XWPFDocument(is);
293             //获取段落
294             List<XWPFParagraph> paras=doc.getParagraphs();
295 
296             for (XWPFParagraph para : paras){
297               //System.out.println(para.getCTP());//得到xml格式
298               //System.out.println(para.getStyleID());//段落级别
299              // System.out.println(para.getParagraphText());//段落内容
300               String titleLvl = getTitleLvl(doc,para);//获取段落级别
301               if("a5".equals(titleLvl)||"HTML".equals(titleLvl)||"".equals(titleLvl)||null==titleLvl){
302                   titleLvl = "8";
303               }
304             //System.out.println(titleLvl+"-----");//0,1,2
305              if(!"8".equals(titleLvl)){
306                 //System.out.println(titleLvl+"===="+para.getParagraphText());
307                 
308                 if("3".equals(titleLvl)) {
309                     
310                     if(concent[i]!=null)
311                     concent[i]=concent[i]+para.getParagraphText();
312                     else
313                     concent[i]=para.getParagraphText();
314                     //System.out.println(concent[i]);
315                 }
316                 if("2".equals(titleLvl)) {
317                     i++;
318                     title[i]=para.getParagraphText();
319                     type[i]=type[i-1];
320                     //System.out.println(title[i]);
321                 }
322                 if("1".equals(titleLvl)) {
323                     i++;
324                     type[i]=para.getParagraphText();     
325                     //System.out.println(title[i]);
326                 }
327             }
328             
329 
330             }
331             for(int j=2;j<title.length;j++) {
332                 if(title[j]!=null) {
333                     String sql = "INSERT INTO shuju (title,concent,type)VALUES (‘"+title[j]+"‘,‘"+concent[j]+"‘,‘"+type[j]+"‘)";
334                     DBUtil jdbc=new DBUtil();
335                     int result=jdbc.executeUpdate(sql);
336                     jdbc.close();
337                     //System.out.println(type[j]);
338                 //System.out.println(title[j]);
339                 //System.out.println(concent[j]);
340                 }
341             }
342         } catch (Exception e) {
343             e.printStackTrace();
344         } finally{
345             try {
346                 if(null!=out){
347                     out.close();
348                 } 
349                 if(null!=is){
350                     is.close();
351                 }
352             }catch (IOException e) {
353                 e.printStackTrace();
354             }
355         }
356     }
357 }

ps:331到341是导入到数据库的需要新建数据库工具类

你自己弄就OK

如果是单纯的读取的话用下面的代码,因为上面比较繁琐我都不太理解,下面的代码比较简单易懂,当然功能相对也少,只能读取所有内容不能识别标题

借鉴的哪一篇博客因为时间太长了,我忘了,抱歉

  1 package com.poi.test;
  2  
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.InputStream;
  6  
  7 import org.apache.poi.POIXMLDocument;
  8 import org.apache.poi.POIXMLTextExtractor;
  9 import org.apache.poi.hwpf.extractor.WordExtractor;
 10 import org.apache.poi.openxml4j.opc.OPCPackage;
 11 import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
 12  
 13 public class testPoi {
 14     /**
 15      * 读取word文件内容
 16      * 
 17      * @param path
 18      * @return buffer
 19      */
 20  
 21     public String readWord(String path) {
 22         String buffer = "";
 23         try {
 24             if (path.endsWith(".doc")) {
 25                 InputStream is = new FileInputStream(new File(path));
 26                 WordExtractor ex = new WordExtractor(is);
 27                 buffer = ex.getText();
 28                 ex.close();
 29             } else if (path.endsWith("docx")) {
 30                 OPCPackage opcPackage = POIXMLDocument.openPackage(path);
 31                 POIXMLTextExtractor extractor = new XWPFWordExtractor(opcPackage);
 32                 buffer = extractor.getText();
 33                 extractor.close();
 34             } else {
 35                 System.out.println("此文件不是word文件!");
 36             }
 37  
 38         } catch (Exception e) {
 39             e.printStackTrace();
 40         }
 41  
 42         return buffer;
 43     }
 44  
 45     public static void main(String[] args) {
 46         // TODO Auto-generated method stub
 47         testPoi tp = new testPoi();
 48         String content = tp.readWord("自己的路径.doc");
 49         //String arr[]=content.split("\\d+");
 50         //String arr[]=content.split("第"+"\\w"+"章");
 51         String arr[]=content.split("\\r\\n");
 52         /*String[] a=arr[13].split("\\d+");
 53         String[] b=a[1].split("\\s+");
 54         System.out.println(b[1]);*/
 55         String[] reci = new String [276];;
 56         for(int i=12,j=0;i<290;i++,j++) {
 57             arr[i]=arr[i]+"1";
 58             if(!arr[i].equals("1")) {
 59             
 60             if(i<27) {//判断页面数是否为单数
 61                 String[] a=arr[i].split("\\d+|\\s+");
 62             if(arr[i]!="\\s+") {//判断该元素是否为连续空格
 63                 if(a.length==2) {//判断该元素是否为标题即分割成2个段
 64                     reci[j]=a[1];
 65                 System.out.println(a[1]);
 66                 }
 67                 else if(a.length==1) {
 68                     reci[j]=a[1];
 69                 System.out.println(arr[i]);
 70                 }
 71                 else//否则该元素是平常元素可以分割成3个段
 72                     {
 73                     reci[j]=a[2];
 74                     System.out.println(a[2]);
 75                     }
 76                 }
 77         }
 78             else {
 79                 String[] a=arr[i].split("\\d{2,3}|\\s+|\\t");
 80                     if(arr[i]!="\\s+") {//判断该元素是否为连续空格
 81                         if(a.length==2) {
 82                             reci[j]=a[1];
 83                             System.out.println(a[1]);
 84                         }
 85                         else if(a.length==1) {
 86                             reci[j]=a[1];
 87                             System.out.println(arr[i]+i);
 88                         }
 89                         else if(a.length==4) {
 90                             reci[j]=a[1];
 91                             System.out.println(a[1]);
 92                         }
 93                         else
 94                             {reci[j]=a[2];
 95                             System.out.println(a[2]);
 96                             }
 97                     }
 98             }
 99         }
100     }
101         String fengefu=reci[0];
102         for(int i=1;i<276;i++) {
103             if(reci[i]!=null)
104         fengefu=fengefu+"|"+reci[i];
105 
106         }
107         System.out.println(reci[275]);
108         System.out.println(fengefu);
109         String arr2[]=content.split(fengefu);
110         for(int i=0;i<200;i++)
111             System.out.println(arr2[i]);
112     }
113 }

还有下面这一种方法,与上面相似

 1 package com.xxx.util;
 2  
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.io.IOException;
 6  
 7 import org.apache.poi.hwpf.extractor.WordExtractor;
 8  
 9 public class DocUtil {
10     /**
11      * 读取doc文件内容
12      * 
13      * @param file
14      *            想要读取的文件对象
15      * @return 返回文件内容
16      * @throws IOException
17      */
18     public static String doc2String(FileInputStream fs) throws IOException {
19         StringBuilder result = new StringBuilder();
20         WordExtractor re = new WordExtractor(fs);
21         result.append(re.getText());
22         re.close();
23         return result.toString();
24     }
25  
26     public static String doc2String(File file) throws IOException {
27         return doc2String(new FileInputStream(file));
28     }
29  
30     public static void main(String[] args) {
31         File file = new File("自己的路径.doc");
32         try {
33             System.out.println(doc2String(file));
34         } catch (IOException e) {
35             e.printStackTrace();
36         }
37     }
38 }

结果截图因为一部分原因就不贴出来了

当然对于poi我还是比较陌生,希望大牛们批评指正

用java语言通过POI实现word文档的按标题提取

原文:https://www.cnblogs.com/zpsblog/p/10568267.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!