Java解析word文档
背景
在互联网教育行业,做内容相关的项目经常碰到的一个问题就是如何解析word文档。
因为系统如果无法智能的解析word,那么就只能通过其他方式手动录入word内容,效率低下,而且人工成本和录入出错率都较高。
疑难点
word解析可以预见的困难主要有以下几个方面:
- word 结构问题 —— word不开源,且含有很多非文本内容,比如图表,而已知的常规方法只能解析纯文本内容,所以如果不知道word内部层级结构,解析将难以进行。
- word 公式问题 —— word公式来源并非单一,可能是用MathType插件生成的latex公式,也可能是用word自带公式编辑器生成的公式,还有可能公式部分手敲,部分使用搜狗输入法或者其它编辑器输入。不同来源处理方式是否一样?且能否有效读取文档各种上下脚标?方便后期展示?
- word 非文本问题 —— word含有很多的非文本内容,比如图表。来源也多样,图表可能是用word自带的画图工具生成的,也有可能是复制粘贴的,不同来源解析方式是否一样?且读取的时候是否能有效获取图片的位置及大小信息?方便文档内容后期在PC端和移动端展示。无论最终方案是什么,肯定是将所有的且需要的非文本信息转换为文本信息。
- word 版本问题 —— word有03、07等好几个版本,还有WPS版本,解析是否要全部兼容?后缀名有docx和doc,是否全部兼容?当然,前提是已经成功解析一种类型。
- word 规范问题 —— 有些word可能是早期制作的,返工代价太大,所以格式内容多样化。而且就算制定word格式规范,新制作的word也无法保证格式一定正确,除非是程序自动生成的文档。举个例子,试题的题序,肉眼无法区分的格式就有好几种。程序只可能尽量覆盖绝大部分情况,考虑的情况越多,解析正确率越高,当然程序也更复杂。



Java解析word
以前曾用Java解析过word文档,所以最先考虑用Java来解决问题,网上搜索方案主要有如下几种:
- jacob:网上资料较少,目前已经实现的是用jacob解析mathtype输入的公式,然后调用word宏命令转成latex,但jacob无法解析word自带的公式。jacob也可以定位word图片总数及word图片位置,但目前没找到将图片另存本地的方法。
- poi:情况与jacob类似。
- Aspose.words:一个商业收费类库,可以使应用程序处理大量的文件任务,支持word、pdf等各种格式操作。但是看文档介绍没有关于公式的处理方案。
Java使用以上几种方案的确解决了部分问题,但很多异常情况还是无法处理,比如无法定位word的批注等。
以下是使用Java定位word图片总数及其位置的代码,更多解决方案请戳 http://www.cnblogs.com/x_wukong/p/4270867.html
package com.latex.test;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class test {
public static void main(String[] args) {
long time1 = System.currentTimeMillis();
ActiveXComponent word = new ActiveXComponent("word.Application");
Dispatch wordObject = (Dispatch) word.getObject();
Dispatch.put((Dispatch) wordObject, "Visible", new Variant(false));
Dispatch documents = word.getProperty("Documents").toDispatch();
Dispatch document = Dispatch.call(documents, "Open", "D://test.docx").toDispatch();
Dispatch wordContent = Dispatch.get(document, "Content").toDispatch();
Dispatch paragraphs = Dispatch.get(wordContent, "Paragraphs").toDispatch();
int paragraphCount = Dispatch.get(paragraphs, "Count").getInt();// 总行数
for (int i = 1; i <= paragraphCount; i++) {
Dispatch paragraph = Dispatch.call(paragraphs, "Item", new Variant(i)).toDispatch();
Dispatch paragraphRange = Dispatch.get(paragraph, "Range").toDispatch();
String paragraphContent = Dispatch.get(paragraphRange, "Text").toString();
System.out.println(paragraphContent);//打印每行内容
Dispatch imgDispatch = Dispatch.get(paragraphRange, "InlineShapes").toDispatch();//图片
int imgCount = Dispatch.get(imgDispatch, "Count").getInt();
System.out.println("第" + i +"行图片总数" + imgCount);
for(int j=1;j<imgCount+1;j++){
Dispatch shape = Dispatch.call(imgDispatch, "Item", new Variant(1)).toDispatch();
Dispatch imageRange = Dispatch.get(shape, "Range").toDispatch();
Dispatch.call(imageRange, "Copy");
Dispatch.call(imageRange, "Paste");
}
}
Dispatch.call(document, "SaveAs" , new Variant( "D://test1.docx"));
Dispatch.call(document, "Close", new Variant(true));
Dispatch.call(word, "Quit");
long time2 = System.currentTimeMillis();
double time3 = (time2 - time1)/1000;
System.out.println(time3 + " 秒.");
}
}
问题分析
用Java预研一段时间后,进展缓慢,很多非文本内容无法解析,归根结底是不知道word内部层级结构。
如果能像html页面那样知道各个节点的构成,那么word解析成功按道理就只是时间问题。
但是word是微软的项目,不开源,所以得去搜索下微软本身是否提供了解析word层级结构的插件。
然后发现了个好东东,名为 Open XML SDK 2.0 Productivity Tool。
下载安装后,把一个word文档拖进面板,就可以看见word层级结构了 ~(~ ̄▽ ̄)~

知道层级结构就可以着手解决解析问题了,其它核心细节这里不方便透露,感兴趣的可以私聊,哈哈 ~~
其他
word中的公式处理是一个比较大的门槛,这里分享一篇不错的文章:
菁优网、梯子网、猿题库的数学公式是如何实现的?
Java解析word文档的更多相关文章
- Apache-Tika解析Word文档
通常在使用爬虫时,爬取到网上的文章都是各式各样的格式处理起来比较麻烦,这里我们使用Apache-Tika来处理Word格式的文章,如下: package com.mengyao.tika.app; i ...
- java 解析XML文档
Java 解析XML文档 一.解析XML文档方式: 1.DOM方式:将整个XML文档读取到内存中,按照XML文件的树状结构图进行解析. 2.SAX方式:基于事件的解析,只需要加载XML中的部分数据,优 ...
- Java解析XML文档(简单实例)——dom解析xml
一.前言 用Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple API for XML)称为SAX和基于树和节点的文档对象模型(Document Object ...
- Java解析XML文档——dom解析xml
一.前言 用Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple API for XML)称为SAX和基于树和节点的文档对象模型(Document Object M ...
- 使用Java生成word文档(附源码)
当我们使用Java生成word文档时,通常首先会想到iText和POI,这是因为我们习惯了使用这两种方法操作Excel,自然而然的也想使用这种生成word文档.但是当我们需要动态生成word时,通常不 ...
- Java POI 解析word文档
实现步骤: 1.poi实现word转html 2.模型化解析html 3.html转Map数组 Map数组(数组的操作处理不做说明) 1.导jar包. 2.代码实现 package com.web.o ...
- Java生成 Word文档的并打印解决方案
户要求用程序生成标准的word文档,要能打印,而且不能变形,以前用过很多解决方案,都在客户严格要求下牺牲的无比惨烈. POI读word文档还行,写文档实在不敢恭维,复杂的样式很难控制不提,想象一下一个 ...
- Java 处理word文档后在前端展示
最新新开发的这个项目需要使用word文档并要求能在前端页面上带格式展示,由于项目不是内部使用,所以不考虑插件类的处理模式,都必须要本地处理完成,前端不需要做什么更新或者说安装就能直接访问,类似于百度文 ...
- 整理关于Java进行word文档的数据动态数据填充
首先我们看下,别人整理的关于Java生成doc 的 资料. java生成word的几种方案 1. Jacob是Java-COM Bridge的缩写,它在Java与微软的COM组件之间构建一座桥梁.使用 ...
随机推荐
- 04 Feasibility of Learning
机器学习是设计算法A,在假设集合H里,根据给定数据集D,选出与实际模式f最为相近的假设g(g可能与f相同,也可能不同). 那什么情况下学习是可行的?即保证g和f是相似的. 1.数据集内的表现g约等于f ...
- MySQL读写分离技术
1.简介 当今MySQL使用相当广泛,随着用户的增多以及数据量的增大,高并发随之而来.然而我们有很多办法可以缓解数据库的压力.分布式数据库.负载均衡.读写分离.增加缓存服务器等等.这里我们将采用读写分 ...
- 【redis专题(8)】命令语法介绍之通用KEY
select num 数据库选择 默认有16[0到15]个数据库,默认自动选择0号数据库 move key num 移动key到num服务器 del key [key ...] 删除给定的一个或多个 ...
- Java基础学习
1,基本类型和引用类型 基本类型就是一个盒子,数据本身就保存在盒子里面,引用类型的盒子里放的是数据的五:地址,通过这个地址来找到数据. 基本数据类型和堆中对象的引用保存在栈中,引用类型保存在堆中. 2 ...
- Html 经典布局(二)
经典布局案例(二): <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- angular ng-bind
<body ng-app=""> <div ng-controller="firstController"> <input typ ...
- MYSQL安装(Linux)
1.首先检查下系统是否已经有mysql相关的安装项 rpm -qa|grep mysql 2.如果有,先删除 rpm -e --nodeps mysql-libs--.el6_5.×86_64 3.接 ...
- Android 性能优化——之图片的优化
Android 性能优化——之图片的优化 在Android性能优化中,我们会发现占内存最大的和对性能影响最大的往往是图片资源,其次是控件资源.相对来说,其他的资源的影响会小一点.这里我就先对图片资源的 ...
- javaweb项目-医者天下 (Spring+SpringMVC+MyBatis)
项目下载地址:http://download.csdn.net/detail/qq_33599520/9826683 项目完整结构图: 项目简介: 医者天下项目是一个基于Spring+SpringMV ...
- Javascript中call和apply
在上一章http://www.cnblogs.com/meiyh/p/6207671.html 我有提到javascript很重要的this关键字,现在我们结合这个关键字使用的下面的两个关键字: ca ...