|
让POI架起Java与Office之间的桥梁二
发表日期:2008-1-5
|
五、通过eventusermodel读取文件 通过eventusermodel读取文件要比使用usermodel复杂得多,但效率也要高不少,因为它要求应用程序一边读取数据,一边处理数据。 eventusermodel实际上模拟了DOM环境下SAX处理XML文档的办法,应用程序首先要注册期望处理的数据,eventusermodel将在碰到匹配的数据结构时回调应用程序注册的方法。使用eventusermodel最大的困难在于你必须熟悉Excel工作簿的内部结构。 在HSSF中,低层次的二进制结构称为记录(Record)。记录有不同的类型,每一种类型由org.apache.poi.hssf.record包中的一个Java类描述。例如,BOFRecord记录表示Workbook或Sheet区域的开始,RowRecord表示有一个行存在并保存其样式信息。 所有具有CellValueRecordInterface接口的记录表示Excel的单元格,包括NumericRecord、LabelSSTRecord和FormulaRecord(还有其他一些,其中部分已被弃置不用,部分用于优化处理,但一般而言,HSSF可以转换它们)。 下面是一个注册事件处理句柄的例子: private EventRecordFactory factory = new EventRecordFactory(); factory.registerListener(new ERFListener() { public boolean processRecord(Record rec) { (got BOF Record); return true; } }, new short[] {BOFRecord.sid}); factory.processRecords(someInputStream); 六、HSSF电子表格结构 如前所述,HSSF建立在POIFS的基础上。具体地说,Excel 97+文件是OLE 2复合文档( OLE 2 Compound Document),底层的OLE 2复合文档保存了一个总是命名为Workbook(Excel 95除外,HSSF不支持Excel 95)的流。 然而,宏和图片并不保存在Workbook流,它们有自己独立的流,有时甚至会放到OLE 2 CDF文件之内的另一个目录。理想情况下,宏也应该被保留,不过目前POI项目中还没有合适的API来处理宏。 每一个流之内是一组记录,一个记录其实就是一个字节数组,可分为记录头、记录体两部分。记录头指明了记录的类型(也即ID)以及后继数据的长度,记录体被分割成多个字段(Field),字段包含数值数据(包括对其他记录的引用)、字符数据或标记。 Excel工作簿的顶级结构: Bla.xls { OLE2CDF headers "Workbook" stream { Workbook { Static String Table Record.. Sheet names… and pointers } Sheet { ROW ROW … NUMBER RECORD (cell) LABELSST Record (cell) … } Sheet } } … images, macros, etc. Document Summary Summary 七、通过HPSF读取文档属性 在Microsoft Word、Excel、Powerpoint等软件中,用户可以通过“文件”→“属性”菜单给文档添加附加信息,包括文档的标题、主题、摘要、类别、要害词等,同时应用软件本身还会加入最后访问的用户、最后访问和修改/打印的日期时间等信息。 文档的属性和正文是分开保存的。如前所述,OLE 2 CDF文件内部就象是一个容器,里面包含许多类似目录和文件的结构,而POIFS就是用来访问其中的文件的工具。这些文件也称为流,文档的属性就保存在POIFS文件系统中专用的流里面。 以一个Word文档为例:虽然在资源治理器中你只看到一个叫做MyFile.doc的文档,其实在这个文档的内部,又包含了一个WordDocument、一个SummaryInformation和一个DocumentSummaryInformation文档;通常还会有其他的文档,这里暂且不管。 你能够猜出这些文档(流)分别包含什么内容吗?不错,WordDocument包含了你在Word里面编辑的文本,文档的属性保存在SummaryInformation和DocumentSummaryInformation流里面。也许将所有属性保存在单个文档里面看起来太简单了,所以Microsoft决心要使用两个流,为了使事情更复杂一点,这两个流的名字前面还加上了八进制的\005字符??这是一个不可打印的字符,因此前面就把它省略了。 Microsoft定义的标准属性有一个好处,它们并不在乎主文档到底是什么类型??不管是Word文档、Excel工作簿还是PowerPoint幻灯。只要你知道如何读取Excel文档的属性,就知道了如何读取其他文档的属性。 读取文档属性其实并不复杂,因为Java程序可以利用POI项目的HPSF包。HPSF是 Horrible Property Set Format的缩写,译成中文就是“讨厌的属性集格式”。HPSF包是POI项目实现的读取属性工具,目前还不支持属性写入。 对于读取Microsoft定义的标准属性,通过HPSF提供的API可以很方便地办到;但假如要读取任意属性集就要用到更一般化的API,可以想象它要比读取标准属性的API复杂不少。本文只介绍读取标准属性的简单API,因为对大多数应用程序来说这已经完全足够了。 下面就是一个读取OLE 2 CDF文档的标题(title)属性的Java程序: import java.io.*; import org.apache.poi.hpsf.*; import org.apache.poi.poifs.eventfilesystem.*; /** * 读取OLE 2文档标题的示例程序, * 在命令行参数中指定文档的文件名字。 */ public class ReadTitle { public static void main(String[] args) throws IOException { final String filename = args[0]; POIFSReader r = new POIFSReader(); r.registerListener(new MyPOIFSReaderListener(), "\005SummaryInformation"); r.read(new FileInputStream(filename)); } static class MyPOIFSReaderListener implements POIFSReaderListener { public void processPOIFSReaderEvent(POIFSReaderEvent event) { SummaryInformation si = null; try { si = (SummaryInformation) PropertySetFactory.create(event.getStream()); } catch (Exception ex) { throw new RuntimeException ("属性集流\"" + event.getPath() + event.getName() + "\": " + ex); } final String title = si.getTitle(); if (title != null) System.out.println("标题: \"" + title + "\""); else System.out.println("该文档没有标题."); } } }
|
|
上一篇:让POI架起Java与Office之间的桥梁一
人气:1236
下一篇:mod_security保障Web Services的安全一(图)
人气:974 |
浏览全部Java的内容
Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐
|
|