前段时间在尝试做一个Android里的万能播放器,能播放各种格式的软件,其中就涉及到了最常用的office软件。查阅了下资料,发现Android中最传统的直接解析读取word,excel的方法主要用了java里第三方包,比如利用tm-extractors-0.4.jar和jxl.jar等,下面附上代码和效果图。
读取word用了tm-extractors-0.4.jar包,代码如下:
package com.example.readword; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import org.textmining.text.extraction.WordExtractor; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.widget.TextView; public class MainActivity extends Activity { /** Called when the activity is first created. */ private TextView text; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView) findViewById(R.id.text); String str = readWord("/storage/emulated/0/ArcGIS/localtilelayer/11.doc"); text.setText(str.trim().replace("", "")); } public String readWord(String file){ //创建输入流用来读取doc文件 FileInputStream in; String text = null; try { in = new FileInputStream(new File(file)); WordExtractor extractor = null; //创建WordExtractor extractor = new WordExtractor(); //进行提取对doc文件 text = extractor.extractText(in); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return text; } }
效果图如下:
只是从网上随便下载的一个文档,我们可以看出,虽然能读取,但是格式的效果并不佳,而且只能读取doc,不能读取docx格式,也不能读取doc里的图片。另外就是加入使用WPF打开过这个doc的话,将无法再次读取(对于只安装WPF的我简直是个灾难)
然后是用jxl读取excel的代码,这个代码不是很齐,就写了个解析的,将excel里每行每列都解析了出来,然后自己可以重新再编辑,代码如下:
package com.readexl; import java.io.FileInputStream; import java.io.InputStream; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.text.method.ScrollingMovementMethod; import android.view.Menu; import android.widget.TextView; import jxl.*; public class MainActivity extends Activity { TextView txt = null; public String filePath_xls = Environment.getExternalStorageDirectory() + "/case.xls"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txt = (TextView)findViewById(R.id.txt_show); txt.setMovementMethod(ScrollingMovementMethod.getInstance()); readExcel(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void readExcel() { try { /** * 后续考虑问题,比如Excel里面的图片以及其他数据类型的读取 **/ InputStream is = new FileInputStream(filePath_xls); //Workbook book = Workbook.getWorkbook(new File("mnt/sdcard/test.xls")); Workbook book = Workbook.getWorkbook(is); int num = book.getNumberOfSheets(); txt.setText("the num of sheets is " + num+ "\n"); // 获得第一个工作表对象 Sheet sheet = book.getSheet(0); int Rows = sheet.getRows(); int Cols = sheet.getColumns(); txt.append("the name of sheet is " + sheet.getName() + "\n"); txt.append("total rows is " + Rows + "\n"); txt.append("total cols is " + Cols + "\n"); for (int i = 0; i < Cols; ++i) { for (int j = 0; j < Rows; ++j) { // getCell(Col,Row)获得单元格的值 txt.append("contents:" + sheet.getCell(i,j).getContents() + "\n"); } } book.close(); } catch (Exception e) { System.out.println(e); } } }
效果图如下:
好吧,这只是个半成品,不过,这个方法肯定是行得通的。
之前说了这么多,很明白的意思就是我对于这两种方法都不是很满意。在这里,我先说下doc和docx的区别(xls和xlsx,ppt和pptx等区别都和此类似)
众所周知的是doc是03及之前版本word所保存的格式,docx是07版本之后保存的格式,简单的说,在doc中,微软还是用二进制存储方式;在docx中微软开始用xml方式,docx实际上成了一个打包的ZIP压缩文件。doc解压得到的是没有扩展名的文件碎片,而docx解压可以得到一个XML和几个包含信息的文件夹。两者比较的结论就是docx更小,而且要读取图片更容易。(参考http://www.zhihu.com/question/21547795)
好吧,回到正题。如何才能解析各种word,excel等能保留原来格式并且解析里面的图片,表格或附件等内容呢。那当然就是html了!不得不承认html对于页面,表格等展示的效果确是是很强大的,原生很难写出这样的效果。在网上找了诸多的资料,以及各个大神的代码,自己又再此基础上修改了下,实现的效果还不错吧。
利用的包是POI(一堆很强大的包,可以解析几乎所有的office软件,这里以doc,docx,xls,xlsx为例)
读取文件后根据不同文件类型分别进行操作。
public void read() { if(!myFile.exists()){ if (this.nameStr.endsWith(".doc")) { this.getRange(); this.makeFile(); this.readDOC(); } if (this.nameStr.endsWith(".docx")) { this.makeFile(); this.readDOCX(); } if (this.nameStr.endsWith(".xls")) { try { this.makeFile(); this.readXLS(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (this.nameStr.endsWith(".xlsx")) { try{ this.makeFile(); this.readXLSX(); }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } returnPath = "file:///" + myFile; // this.view.loadUrl("file:///" + this.htmlPath); System.out.println("htmlPath" + this.htmlPath); }先贴上公用的方法,主要是设置生成的html文件保存地址:
public void makeFile() { String sdStateString = android.os.Environment.getExternalStorageState();// 获取外部存储状态 if (sdStateString.equals(android.os.Environment.MEDIA_MOUNTED)) { // 确认sd卡存在,原理不知,媒体安装?? try { File sdFile = android.os.Environment .getExternalStorageDirectory();// 获取扩展设备的文件目录 String path = sdFile.getAbsolutePath() + File.separator + "library";// 得到sd卡(扩展设备)的绝对路径+"/"+xiao File dirFile = new File(path);// 获取xiao文件夹地址 if (!dirFile.exists()) { // 如果不存在 dirFile.mkdir();// 创建目录 } File myFile = new File(path + File.separator +filename+ ".html");// 获取my.html的地址 if (!myFile.exists()) { // 如果不存在 myFile.createNewFile();// 创建文件 } this.htmlPath = myFile.getAbsolutePath();// 返回路径 } catch (Exception e) { } } }然后是读取doc:
private void getRange() { FileInputStream in = null; POIFSFileSystem pfs = null; try { in = new FileInputStream(nameStr); pfs = new POIFSFileSystem(in); hwpf = new HWPFDocument(pfs); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } range = hwpf.getRange(); pictures = hwpf.getPicturesTable().getAllPictures(); tableIterator = new TableIterator(range); }
public void readDOC() { try { myFile = new File(htmlPath); output = new FileOutputStream(myFile); presentPicture=0; String head = "<