解析word文档,获取相应的数据,并封装成相应的javaBean(二)

本文介绍了一种使用Java程序解析Word文档的方法,重点是提取完整的数学试题内容,包括题目、选项、答案、考点等,并通过二次切割获得更精确的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 该类主要是用程序来读取word文本,并拿到你想要的内容, 我这里主要是解析一道完整的数学试题, 包括(题目,选项,答案,考点,分析,解答,点评)等内容

这里写图片描述

package com.ilike.poi;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.PicturesTable;
import org.apache.poi.hwpf.usermodel.CharacterRun;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.Range;

import com.ilike.utils.RandomNameUtil;

/**
*
*
* 实现思路:
* 1.先逐字读取整个word文档,并替换里面的图片,回车符,空格符等内容
* 2.将替换后的文本做初次切割,切出含有题目,选项,答案等内容的片段,封装成一个map集合
* 3.将初次切割后的内容片段拿来做二次切割(调用相应的切割方法进行切割),切出自己想要的内容
*
* @author 桑伟东
*
* 注意:这个切割只实现了简单的读写,读取的2的平方这样的数据依旧有问题,但会很快在下一次发表时实现
*/
public class WordToHtml7 {

public static String readFile = "F:\\doc_test\\swdTest1.doc";//要解析的文档
public static String outPath = "F:\\temp_image\\";//文档中图片的存储路径
public static String ziful = "【";//文档中含有的符号
public static String zifur = "】";//文档中含有的符号
private static final short ENTER_ASCII = 13;// 回车符
private static final short SPACE_ASCII = 32;// 空格
private static final short KONGGE_ASCII = 9;// 空格是9(这个空格是我自己调试程序发现的,正规的空格对应的编码应该是32)

public static void main(String[] args) throws Exception {
    //1.替换图片及回车符等
    String html = replacePhotoAndEnter(readFile);
    //2.初次切割
    Map<String, String> map = splitItems(html);
    //3.二次切割
    secondSplit(map);
}

/**
 * 读取word文本,替换里面的图片以及空格,回车符等 说明:将图片替换成相应的image标签,将空格替换成&nbsp;,将回车符替换成</br>
 * 
 * @param fileName
 *            需要替换的文件
 * @return 替换后的字符串文本
 * @throws Exception
 */
public static String replacePhotoAndEnter(String fileName) throws Exception {
    // 1.创建字节输入流读取要解析的文档
    FileInputStream in = new FileInputStream(new File(fileName));
    // 2.创建文档对象
    HWPFDocument doc = new HWPFDocument(in);
    // 3.取得文档中字符的总数
    int length = doc.characterLength();
    // 4.获取PicturesTable对象
    PicturesTable pTable = doc.getPicturesTable();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < length; i++) {
        Range range = new Range(i, i + 1, doc);
        CharacterRun cr = range.getCharacterRun(0);
        // System.out.println(cr.text()+"------"+(short)(cr.text().charAt(0)));
        // 1.判断该字符是否是照片
        if (pTable.hasPicture(cr)) {
            // 是照片
            Picture pic = pTable.extractPicture(cr, false);
            String file = outPath + RandomNameUtil.getRandomName6N() + ".png";
            // 创建一个输出流
            OutputStream out = new FileOutputStream(file);
            // 将图片写出去
            pic.writeImageContent(out);
            // 替换图片
            String webPath = "<image src='" + file + "'/>";
            sb.append(webPath);
            // 2.判断该字符是否是回车符,如果是就用<br/>替换
        } else if (cr.text().charAt(0) == ENTER_ASCII) {
            sb.append("<br/>");
            // 3.判断该字符是否是空格符,如果是用&nbsp;替换
        } else if (cr.text().charAt(0) == SPACE_ASCII) {
            sb.append("&nbsp;");
            // 4.判断该字符是否是空格符,如果是用&nbsp;替换(非正规替换)
        } else if (cr.text().charAt(0) == KONGGE_ASCII) {
            sb.append("&nbsp;");
            // 5.如果所有的这些都不是,默认为普通文本
        } else {
            sb.append(cr.text());
        }
    }
    return sb.toString();
}

/**
 * 该方法将替换后的文本做初次切割,切割出含有想要内容的粗糙文本(含有不想要的内容), 最后封装成一个map返回
 * 
 * @param src
 *            初次切割的文本
 * @return
 */
public static Map<String, String> splitItems(String src) {
    Map<String, String> map = new HashMap<String, String>();
    // 1.获取“【答案】”的位置
    Integer answerPoi = src.indexOf("【答案】");
    // 2.截取包含测试题的内容,并保存输出
    String test = src.substring(0, answerPoi);
    map.put("test", test);
    // System.out.println("test:"+test);
    // 3.获取【考点】的位置
    Integer keyPoi = src.indexOf("【考点】");
    // 4.截取包含答案的内容,并保存输出
    String answer = src.substring(answerPoi, keyPoi);
    map.put("answer", answer);
    // System.out.println("answer:"+answer);
    // 5.获取【分析】的位置
    Integer analysePoi = src.indexOf("【分析】");
    // 6.截取包含考点的内容,并保存输出
    String keys = src.substring(keyPoi, analysePoi);
    map.put("keys", keys);
    // System.out.println("keys:"+keys);

    // 7.获取【解答】的位置
    Integer jiedaPoi = src.indexOf("【解答】");
    // 8.截取包含分析的内容,并保存输出
    String analyse = src.substring(analysePoi, jiedaPoi);
    map.put("analyse", analyse);
    // System.out.println("analyse:"+analyse);

    // 9.获取【点评】的位置
    Integer commentPoi = src.indexOf("【点评】");
    // 10.截取包含考点的内容,并保存输出
    String jieda = src.substring(jiedaPoi, commentPoi);
    map.put("jieda", jieda);
    // System.out.println("jieda:"+jieda);

    // 11.截取包含点评的内容,并保存输出
    String comment = src.substring(commentPoi, src.length());
    map.put("comment", comment);
    // System.out.println("comment:"+comment);
    return map;
}

/**
 * 对初次剪切后的各种文本进行二次深加工,切出真正想要的内容 如果要封装成相应的Bean,在这里就可以封装,这个较为简单,不再赘述
 * 
 * @param map
 *            初次切割后的文本
 */
public static void secondSplit(Map<String, String> map) {
    for (String item : map.keySet()) {
        if (item.equals("test")) {
            // 是题目,调用题目剪切方法进行切割
            String test = testSplit(map.get("test"));
            System.out.println("test:" + test);
            // 这里面也含有选项,顺带切出选项
            String option = optionSplit(map.get("test"));
            System.out.println("option:" + option);
        } else if (item.equals("answer")) {
            // 是答案,调用答案剪切方法进行切割
            String answer = answerSplit(map.get("answer"));
            System.out.println("answer:" + answer);
        } else if (item.equals("keys")) {
            // 是考点,调用考点剪切方法进行切割
            String keys = keysSplit(map.get("keys"));
            System.out.println("keys:" + keys);
        } else if (item.equals("analyse")) {
            // 是分析,调用分析剪切方法进行切割
            String analyse = analyseSplit(map.get("analyse"));
            System.out.println("analyse:" + analyse);
        } else if (item.equals("comment")) {
            // 是点评,调用点评剪切方法进行切割
            String comment = commentSplit(map.get("comment"));
            System.out.println("comment:" + comment);
        } else if (item.equals("jieda")) {
            // 是解答,调用解答剪切方法进行切割
            String jieda = jiedaSplit(map.get("jieda"));
            System.out.println("jieda:" + jieda);
        } else {
            System.out.println("未知的东东");
        }

    }

}

/**
 * 从含有题目的文本剪切出题目
 * 
 * @param srcTest
 * @return
 */
private static String testSplit(String srcTest) {
    // 1.获取"一.选择题"的位置
    Integer pesition1 = srcTest.indexOf("一.选择题");
    // 2.获取"A."的位置
    Integer pesition2 = srcTest.indexOf("A.");
    // 3.切出题目
    String testtext = srcTest.substring(pesition1, pesition2);
    // System.out.println("test:"+testtext);
    // 4.获取第一个和最后一个“<br/>”的位置
    testtext = testtext.substring(testtext.indexOf("<br/>") + "<br/>".length(), testtext.lastIndexOf("<br/>"));
    // System.out.println("test:"+testtext);
    return testtext;
}

/**
 * 从含有选项的文本里切出选项
 * 
 * @param srcOption
 * @return
 */
private static String optionSplit(String srcOption) {
    // 1.获取"A."的位置
    Integer pesition1 = srcOption.indexOf("A.");
    // 2.获取最后一个“<br/>”的位置
    Integer pesition2 = srcOption.lastIndexOf("<br/");
    // 3.切出option的内容
    String option = srcOption.substring(pesition1, pesition2);
    // System.out.println("option:"+option);
    return option;
}

/**
 * 从含有答案的文本里切出选项
 * 
 * @param srcOption
 * @return
 */
// answer:【答案】D<br/>
private static String answerSplit(String answerSrc) {
    // 1.获取"【答案】"的位置
    Integer pesition1 = answerSrc.indexOf("【答案】");
    // 2.获取最后一个“<br/>”的位置
    Integer pesition2 = answerSrc.lastIndexOf("<br/");
    // 3.切出answer的内容
    String answer = answerSrc.substring(pesition1, pesition2);
    // System.out.println("answer:"+answer);
    return answer;
}

/**
 * 从含有考点的文本里切出选项
 * 
 * @param srcOption
 * @return
 */
// keys:【考点】4C:完全平方公式.菁优网版权所有<br/>
private static String keysSplit(String keysSrc) {
    // 1.获取"【考点】"的位置
    Integer pesition1 = keysSrc.indexOf("【考点】");
    // 2.获取最后一个“<br/>”的位置
    Integer pesition2 = keysSrc.lastIndexOf("<br/");
    // 3.切出keys的内容
    String keys = keysSrc.substring(pesition1, pesition2);
    // System.out.println("keys:"+keys);
    return keys;
}

/**
 * 从含有分析的文本里切出选项
 * 
 * @param srcOption
 * @return
 */
// analyse:【分析】首先把a2+b2+c2﹣ab﹣bc﹣ac变为<image
// src='F:\temp_image\72d4db.png'/>(2a2+2b2+2c2﹣2ab﹣2bc﹣2ac),然后利用完全平方公式变为三个完全平方式,然后代入已知数据即可求解.<br/>
private static String analyseSplit(String analyseSrc) {
    // 1.获取"【分析】"的位置
    Integer pesition1 = analyseSrc.indexOf("【分析】");
    // 2.获取最后一个“<br/>”的位置
    Integer pesition2 = analyseSrc.lastIndexOf("<br/");
    // 3.切出analyse的内容
    String analyse = analyseSrc.substring(pesition1, pesition2);
    // System.out.println("analyse:"+analyse);
    return analyse;
}

/**
 * 从含有解答的文本里切出选项
 * 
 * @param srcOption
 * @return
 */
// jieda:【解答】解:∵a2+b2+c2﹣ab﹣bc﹣ac<br/>=<image
// src='F:\temp_image\1c1dde.png'/>(2a2+2b2+2c2﹣2ab﹣2bc﹣2ac)<br/>=<image
// src='F:\temp_image\829ed0.png'/>[(a2﹣2ab+b2)+(b2﹣2bc+c2)+&nbsp;(c2﹣2ac+a2)]<br/>=<image
// src='F:\temp_image\e7ded0.png'/>[(a﹣b)2+(b﹣c)2+(c﹣a)2]<br/>而a=2000x+2001,b=2000x+2002,c=2000x+2003,<br/>∴a﹣b=2000x+2002﹣(2000x+2001)=1,<br/>同理&nbsp;b﹣c=﹣1,c﹣a=2,<br/>∴a2+b2+c2﹣ab﹣bc﹣ac<br/>=<image
// src='F:\temp_image\ee910f.png'/>[(a﹣b)2+(b﹣c)2+(c﹣a)2]<br/>=3.<br/>故选D.<br/>
private static String jiedaSplit(String jiedaSrc) {
    // 1.获取"【解答】"的位置
    Integer pesition1 = jiedaSrc.indexOf("【解答】");
    // 2.获取最后一个“<br/>”的位置
    Integer pesition2 = jiedaSrc.lastIndexOf("<br/");
    // 3.切出jieda的内容
    String jieda = jiedaSrc.substring(pesition1, pesition2);
    // System.out.println("jieda:"+jieda);
    return jieda;
}

/**
 * 从含有点评的文本里切出选项
 * 
 * @param srcOption
 * @return
 */
// comment:【点评】此题主要考查了利用完全平方公式进行代数式变形,然后求复杂代数式的值,解题的关键是把所求代数式变形,从而大大简化计算过程.题目难度比较大.<br/><br/>
private static String commentSplit(String commentSrc) {
    // 1.获取"【点评】"的位置
    Integer pesition1 = commentSrc.indexOf("【点评】");
    // 2.获取最后一个“<br/>”的位置
    Integer pesition2 = commentSrc.lastIndexOf("<br/");
    // 3.切出comment的内容
    String comment = commentSrc.substring(pesition1, pesition2);
    // System.out.println("comment:"+comment);
    return comment;
}

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值