POI事件模式指北(一)-Excel2003
POI事件模式指北(一)-Excel2003
1、简介
Excel2003(.xls)是Microsoft Excel2003之前版本要求的格式,POI提供两种方式读取这种类型的文件
1、用户模式(User API):将xls文件全部读进内存,然后以dom结构处理;
2、事件模式(event API):用流的形式读取文件,占用内存较少,适用于愿意学习低级API结构的开发人员,需要对Excel文件的各个部分有基本的了解。
2、XLS文件介绍
XLS后缀的文件包括Worksheet文档和Workbook文档两种。是Excel 4.0及以前版本为Worksheet文档;以后的版本为Workbook文档。
2.1、Worksheet Document
Worksheet文档只包括一个sheet,默认的文件后缀是“XLS”。
2.2、Workbook Document
Workbook文档可以包含多个sheet,每个Workbook文档都包含一个全局设置,叫做(workbook globals)。
3、OLE 2复合文档系统 - POIFS
就像上面展示的,xls实际上实际上以复合文档的形式组织在一起;然后POI以流的形式读取。
3.1、Workbook文件流 (Workbook Streams)
Workbook文件流会先读取workbook globals Substream,然后再依次读取每个Sheet Substream。
这里展示的是Workbook文档的文件流结构。鉴于我们基本不会遇到Worksheet Document,下面将只针对Workbook Document来讨论。更多相关信息请参见文末参考链接。
3.2、Workbook Records
文件中的各种流会以Record的形式被解析,每个Record都包含特定的数据和格式等相关信息。
例如BOFRecord记录了Workbook或Sheet的开始、EOFRecord记录了Workbook或Sheet的结束等等。。。
org.apache.poi.hssf.record包下面包括了各种Record类,我们需要的数据和文档结构就包含在各个Record类中。
我们常用的Record差不多有下面这些:
// 记录了sheetName BoundSheetRecord // Workbook、Sheet的开始 BOFRecord // 存在单元格样式的空单元格 BlankRecord // 布尔或错误单元格 BoolErrRecord // 公式单元格 FormulaRecord // 公式的计算结果单元格 StringRecord // 文本单元格 LabelRecord // 共用的文本单元格 LabelSSTRecord // 数值单元格:数字单元格和日期单元格 NumberRecord // Workbook、Sheet的结束 EOFRecord
4、解析文件
想要利用事件模式的API,需要将文件用FileSystem将文件读取进来
1、继承HSSFListener接口,创建自己的监听器listener;
利用recordsid,recordsid是org.apache.poi.hssf.record中的类中包含的静态引用号(例如BOFRecord.sid)
2、使用HSSFRequest.addListener(yourlistener,recordsid)注册监听器,也可以用HSSFRequest.addListenerForAllRecords(mylistener)添加全部监听器;
3、构造org.apache.poi.poifs.filesystem.FileSystem的实例并将其传递给XLS文件输入流;
4、将输入流DocumentInputStream解析成record;
5、根据注册的监听类型分别处理各种类型的record;
4.1、org.apache.poi.hssf.eventusermodel.HSSFEventFactory
事件模式常用的方法一般是下面两个:
/** * 将一个文件处理为基本的Record事件 * @param req 一个HSSFRequest实例,记录了Record的所有监听器 * @param fs 包含WorkBook的POIFS文件系统 */ HSSFEventFactory.processWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) /** * 将一个文件处理为基本的Record事件 * @param req 一个HSSFRequest实例,记录了Record的所有监听器 * @param in 包含WorkBook的DirectoryNode的输入流 */ HSSFEventFactory.processEvents(HSSFRequest req, InputStream in)
5、事件模式实例
这个例子是参照POI官网提供的代码,针对的是POI最新的版本POI 4.0.1;但我们常用的3.x也基本都可以正常运行
EventExample.class
/** * 此示例显示如何使用事件API读取文件 */ public class EventExample implements HSSFListener { private SSTRecord sstrec; /** * 此方法监听传入记录并根据需要处理它们 * @param record读取时找到的记录 */ public void processRecord(Record record) { switch (record.getSid()) { //BOFRecord可以表示工作表或工作簿的开头 case BOFRecord.sid: BOFRecord bof = (BOFRecord) record; if (bof.getType() == bof.TYPE_WORKBOOK) { System.out.println("监听到工作表"); } else if (bof.getType() == bof.TYPE_WORKSHEET) { System.out.println("监听到工作簿"); } break; case BoundSheetRecord.sid: BoundSheetRecord bsr = (BoundSheetRecord) record; System.out.println("工作簿名称: " + bsr.getSheetname()); break; case RowRecord.sid: RowRecord rowrec = (RowRecord) record; System.out.println("监听到行, 第一行位于 " + rowrec.getFirstCol() + " 最后一行位于 " + rowrec.getLastCol()); break; case NumberRecord.sid: NumberRecord numrec = (NumberRecord) record; System.out.println("发现单元格: " + numrec.getValue() + " 位于 " + numrec.getRow() + " 行, " + numrec.getColumn() + " 列" ); break; case LabelSSTRecord.sid: LabelSSTRecord lrec = (LabelSSTRecord) record; System.out.println("找到文本值: " + sstrec.getString(lrec.getSSTIndex())); break; } } / ** * 读取Excel文件,并打印出文件内容 * @param args 要读取的文件 * @throws IOException * / public static void main(String[] args) throws IOException { // 使用输入的文件创建一个新的文件输入流 FileInputStream fin = new FileInputStream(args[0]); // 创建一个新的org.apache.poi.poifs.filesystem.Filesystem POIFSFileSystem poifs = new POIFSFileSystem(fin); // 在InputStream中获取Workbook流 InputStream din = poifs.createDocumentInputStream("Workbook"); // 构造出HSSFRequest对象 HSSFRequest req = new HSSFRequest(); // 注册全部的监听器 req.addListenerForAllRecords(new EventExample()); // 创建事件工厂 HSSFEventFactory factory = new HSSFEventFactory(); // 根据文档输入流处理我们监听的事件 factory.processEvents(req, din); // 关闭文件输入流 fin.close(); // 关闭文档输入流 din.close(); System.out.println("读取结束"); } }
6、后记
本文主要介绍了利用POI读取xls文件,xls文件因为是Excel2003以前的版本都使用的格式,其实不同版本之间还是有一些不同的,如果遇到了奇怪的问题不妨考虑一下版本的问题。这篇文章没有涉及d的实用部分,会在之后的文章中写出来。
参考链接
Apache POI官网: https://poi.apache.org
XLS规范[PDF]: http://www.openoffice.org/sc/excelfileformat.pdf
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
IntelliJ IDEA 中看到 classes, sources, javadocs 三种jar的区别和各自的作用
在 intelliJ idea 里面看到 ,Project Structure——》 Libraries ——》 Sources 的路径是红色的 看图会比较好。以guava包为例来说明。 可以看到在这看整个maven项目的依赖时,发现如图的情况,这红色是什么情况,是报错吗?需要处理吗?这3个不同jar都是什么东西,各自有啥作用。大概会有这么些疑问吧。️。 假如在依赖库如上的情况下,你点进去,看guava的源码,会有下图的效果。 给你2个选择,一个是选则source,一个是下载source。注意,这个时候,你看到的文件是class文件,是可以直接运行的文件,之所以能看到内部的具体实现,是idea给你自动逆转换啦。感谢idea吧 (记得当年刚刚工作的时候,使用的eclipse,然后debug的时候,假如要进入这些个没有sources的jar的时候,就进不去这个class文件,他还傻乎乎的给个弹窗,让我倒入sources文件,还是idea高级,直接喊你下载。) 这个时候点击download sources,下载源码。 这个时候,你看到的文件,就变成啦Java文件,而且,还带上了很多的注释。 ...
- 下一篇
python中的venv 模块 -- 创建虚拟化的项目环境
前言 在使用 python 制作网页的过程中,我们往往需要先将站点的目录“虚拟化”。虚拟化其实就是将当前文件下程序的运行环境与整个系统的环境隔离。那么为什么我们要将一个项目虚拟化呢? 1.不进行虚拟化会产生的问题 在平时使用 python 时,有可能会遇到这几个常见的问题: 1.当运行的项目处于不同版本时(如 python 2.7/3.7 ),要通过切换 python 解释器的版本来运行程序(或要使用 python2/3 pip/pip3 等指令来对应不同的版本)。 2.有时做一个项目要用到许多第三方模块,但是其他项目基本不会用。如果直接 pip install 到系统中,项目删除后清除安装过的模块会很麻烦。 3.做完一个项目后,你希望能够不再一次安装它依赖的模块,就能在另外一个系统上直接运行。 4.你的项目暂时运行在一个旧版的第三方模块上,而新版的第三方模块不兼容你所写的程序。你既希望能够让原来的项目在旧版本上继续正常运行,又希望能够在另一个项目中使用新版本。 如果你遇到过上面这四个问题,并且希望能够改善这一些繁琐的配置过程,那么你就可以尝试对你的项目进行“虚拟化”。 **学习从来不...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS6,CentOS7官方镜像安装Oracle11G
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块