最近打算实现一个功能:在Android中加载显示Word文档,当然这里不是使用外部程序打开。查看一些资料后,打算采用poi实现,确定了以下实现思路:
- 将ftp中的word文档下载到本地。
- 调用poi将word文档转成html格式并保存到本地
- 使用WebViewer加载显示本地html
这里略去下载word文档到本地不谈,仅仅后面两步,看起来还是比较简单的,网上也有相关代码。不过在使用过程中遇到了两个大的问题,着实让笔者费了一番脑筋。这里给大家列出来,希望能帮助大家节省些时间。
- 下载poi-bin-3.9-20121203.tar.gz并解压,提取查看Office文档所依赖的包。
- word相关操作依赖于poi-3.9-20121203.jar和poi-scratchpad-3.9-20121203.jar两个包,将其加入到Android程序的libs文件夹中。
- 将word转html并保存到本地,然后使用WebViewer加载显示本地html。整个代码如下
package com.example.office; import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.w3c.dom.Document; import android.os.Bundle;
import android.app.Activity;
import android.webkit.WebSettings;
import android.webkit.WebView; public class MainActivity extends Activity { private String docPath = "/mnt/sdcard/documents/";
private String docName = "test.doc";
private String savePath = "/mnt/sdcard/documents/"; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String name = docName.substring(0, docName.indexOf("."));
try {
if(!(new File(savePath+name).exists()))
new File(savePath+name).mkdirs();
convert2Html(docPath+docName,savePath+name+".html");
} catch (Exception e){
e.printStackTrace();
}
//WebView加载显示本地html文件
WebView webView = (WebView)this.findViewById(R.id.office);
WebSettings webSettings = webView.getSettings();
webSettings.setLoadWithOverviewMode(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
webView.loadUrl("file:/"+savePath+name+".html");
} /**
* word文档转成html格式
* */
public void convert2Html(String fileName, String outPutFile)
throws TransformerException, IOException,
ParserConfigurationException {
HWPFDocument wordDocument = new HWPFDocument(new FileInputStream(fileName));
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()); //设置图片路径
wordToHtmlConverter.setPicturesManager(new PicturesManager()
{
public String savePicture( byte[] content,
PictureType pictureType, String suggestedName,
float widthInches, float heightInches )
{
String name = docName.substring(0,docName.indexOf("."));
return name+"/"+suggestedName;
}
} ); //保存图片
List<Picture> pics=wordDocument.getPicturesTable().getAllPictures();
if(pics!=null){
for(int i=0;i<pics.size();i++){
Picture pic = (Picture)pics.get(i);
System.out.println( pic.suggestFullFileName());
try {
String name = docName.substring(0,docName.indexOf("."));
pic.writeImageContent(new FileOutputStream(savePath+ name + "/"
+ pic.suggestFullFileName()));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
wordToHtmlConverter.processDocument(wordDocument);
Document htmlDocument = wordToHtmlConverter.getDocument();
ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(out); TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
out.close();
//保存html文件
writeFile(new String(out.toByteArray()), outPutFile);
} /**
* 将html文件保存到sd卡
* */
public void writeFile(String content, String path) {
FileOutputStream fos = null;
BufferedWriter bw = null;
try {
File file = new File(path);
if(!file.exists()){
file.createNewFile();
}
fos = new FileOutputStream(file);
bw = new BufferedWriter(new OutputStreamWriter(fos,"utf-8"));
bw.write(content);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
if (bw != null)
bw.close();
if (fos != null)
fos.close();
} catch (IOException ie) {
}
}
}
}
activity_main.xml如下
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" > <WebView
android:id = "@+id/office"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world"
tools:context=".MainActivity"/>
</RelativeLayout>
上面代码中convert2Html用于将word文档转换html。下面的代码则是使用WebViewer加载显示本地html文件。
WebView webView = (WebView)this.findViewById(R.id.office);
WebSettings webSettings = webView.getSettings();
webSettings.setLoadWithOverviewMode(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true);
webView.loadUrl("file:/"+savePath+name+".html");
下面来详细说说存在的两个问题
09-23 17:40:12.350: W/System.err(29954): java.lang.NullPointerException
09-23 17:40:12.350: W/System.err(29954): at org.apache.poi.hwpf.converter.AbstractWordUtils.compactChildNodesR(AbstractWordUtils.java:146)
child2.getParentNode().removeChild( child2 );
i--;
更改为
if(child2.getParentNode()!=null){
child2.getParentNode().removeChild( child2 );
i--;
}
然而这里需要重新编译AbstractWordUtils.java类,将源工程下载后,找到AbstractWordUtils.java后,试验了以下方法。
- 直接使用javac编译,会提示很多类库找不到
- 使用反编译工具,反编译后更改个文字还可以,更改代码就有点勉强了。
- 将整个poi导入eclipse后重新编译,工作量太大,没有进行尝试。
- 将AbstractWordUtils.java,poi-3.9-20121203.jar,poi-scratchpad-3.9-20121203.jar放到同一目录下,非必需。
- 通过引用已有的两个包进行编译,编译命令如下:javac -cp d:\poi-3.9-20121203.jar;d:\poi-scratchpad-3.9-20121203.jar; d:\AbstractWordUtils.java ;编译后生成AbstractWordUtils.class文件。
- 将poi-3.9-20121203.jar的后缀改成zip,将AbstractWordUtils.class拖到zip中覆盖掉原有文件,然后将后缀zip改成jar即可。点击此处下载更改好的poi-3.9-20121203.jar。
-startup
plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.100.v20110502
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
-vmargs
-Xms256m
-Xmx800m
- 目前poi只针对2003的doc格式,不支持2007及其以上的docx格式。
- 经测试发现,偶尔会出现的问题,不知如何解决。这里建议内部程序简单预览,外部程序打开word文档详细浏览的方式。
- poi和android API的版本或ADT版本有关;有的在java环境下良好,在android环境下就有问题,还请多多注意。
- 整个工程实例代码请点击此处。
Android中使用POI加载与显示word文档的更多相关文章
-
arcgis android 中shapefile的加载
前言 本文为大家分享arcgis android 中shapefile的加载,默认你有java环境,懂一定的android基础知识,默认你已经安装android studio.如缺乏以上环境和知识,请 ...
-
Android中的动态加载机制
在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...
-
Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案
我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...
-
Android中的Glide加载图片
注意:在Android Studio的项目的build.gradle中添加: compile 'com.github.bumptech.glide:glide:3.6.1' 然后同步一下 目录: 使用 ...
-
Android中的分页加载
//----------------------MainActivity中--------------------------------------------------- package com ...
-
webbrowser控件显示word文档
参照某网站上的步骤(http://www.kuqin.com/office/20070909/968.html)首先,在Visual Studio中创建一个C#语言的Windows应用程序,然后在左侧 ...
-
Android中ListView动态加载数据
1. 引言: 为了提高ListView的效率和应用程序的性能,在Android应用程序中不应该一次性加载ListView所要显示的全部信息,而是采取分批加载策略,随着用户的滑动,动态的从后台加载所需的 ...
-
Android中一张图片加载后所占用内存大小的获取与测试
Android程序中一旦加载的图片比较多,就有可能出现Out of Memory而导致程序崩溃.这个一方面是因为Android系统本身对于每个单独的进程有内存大小的限制(有16M,64M,128M,2 ...
-
MVP+RXJAVA+RecyclerView实现sd卡根目录下的所有文件中的照片加载并显示
初学Rxjava,目前只能遍历加载指定目录下的所有文件夹中的照片,文件夹中如果还嵌套有文件夹目前还没找到实现方法. 先看mvp目录结构: 很抱歉,没有model. 接下来是view层的接口代码和pre ...
随机推荐
-
android存储方式的应用场景
作为一个完整的应用程序,数据存储操作是必不可少的.因此,Android系统一共提供了四种数据存储方式.分别是:SharePreference.文件存储.SQLite. Content Provider ...
-
JavaWeb开发学习(一)-JavaWeb开发概述
1.Web相关概念 Web程序也就是一般所说的网站,由服务器.客户端浏览器以及网络组成.Web程序的好处是使用简单,不需要安装.学习,有一台电脑.一根网线就可以使用.Web程序不是一般意义上的网站.网 ...
-
BZOJ1931 : [Shoi2007]Permutation 有序的计数
枚举LCP以及下一位变小成什么,统计出剩下的有几个可以在原位置. 然后枚举剩下的至少有几个在原位置,容斥计算答案. 时间复杂度$O(n^3)$. #include<cstdio> type ...
-
matlab如何连同换行也输入txt中
\r是回车符,\n是换行符,两者结合方能在txt显示为换行 fidID = fopen('test.txt', 'w+'); str='string'; fprintf(fidID,'%s \r\n' ...
-
break , continue , exit
break , continue , exit 例一:#!/bin/bash . /etc/init.d/functions `;do ];then #continue #没有数字3 break #e ...
-
c++ string用法
首先,为了在我们的程序中使用string类型,我们必须包含头文件 .如下: #include //注意这里不是string.h string.h是C字符串头文件 1.声明一个C++字符串 声明一个字 ...
-
Android开发系列(一)Activity与Fragment获取屏幕获取屏幕像素的不同方式
Activity中常用的获取屏幕像素代码: //获取屏幕像素相关信息 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getD ...
-
JSP内置对象1(request,response,session)
request对象 response对象:请求重定向与请求转发的区别. session对象:表示客户端与服务器的一次会话,也就是用户浏览网站所花费的时间.在服务器的内存中保存着不同用户的session ...
-
20181115 python-第一章学习小结part2
Python基本知识 变量,用来存储中间计算结果,在后面可进行调用被使用的东西,叫做变量. 变量的命名规则: 字母,数字,下划线组合 不能用数字开头 常见的关键字不能用啊 常量,不会变的量,称作常量. ...
-
Session执行机制与原理
Session执行机制与原理 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 什么是Session 首先了解一下Session的中文意思:一次会话,什么是一次会话呢?我举个例子:就我们现 ...