官方例子指的是
上一章内容:关于Apache-POI的学习与工具类封装日志【1】----如何从官方文档的信息中部署环境并进行初期测试
关于HWPFDocument
示例代码中使用了HWPFDocument,通过Apache-POI官网的api文档我们可以发现,关于这个类的描述是:
This class acts as the bucket that we throw all of the Word data structures into.
经过一层层深入,确认这个类的本质也是流,因为POI包顶部类POIDocument实现的是java的Closeable。深入检阅与测试api文档,作出对官网给出的三个构造方法的理解:
- HWPFDocument(DirectoryNode directory)
该方法看介绍与参数分析,应该是一个通过word的特殊节点获得word操作对象的节点操作方法。关于这个构造函数的使用,光看文档有一点费劲,废了我不少查阅时间,所以我尝试了不少方法使用它,发现这个方法并不实用,因为从使用hwpf的角度来说,我只在其父类POIDocument里看到这么一个获取节点的方法。
public DirectoryNode getDirectory() {
return this.directory;
}
可以看出它无参,我没办法使用下标方式直接获取节点。并且,在关于这个方法的卡片说明里,提到了一个叫POIFSFileSystem的类,经过查阅父类,它也是一种流对象,并且POIFSFileSystem和HWPFDocument无POI设计下的同一父类或接口,交点只在java包下的Closeable。
- HWPFDocument(java.io.InputStream istream)
该方法看介绍与参数分析,应该是一个通过普通输入流对象获得word操作对象的方法。关于这个构造函数的使用,其实在上一章已经有很好的体验,这里就不再重提。
- HWPFDocument(POIFSFileSystem pfilesystem)
该方法看介绍与参数分析,应该是一个通过POIFSFileSystem对象获得word操作对象的方法。关于这个构造函数的使用也是很简单,类似于流对象转换。
一般使用方法为:
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("src/main/resources/static/demo.doc"));
HWPFDocument hwpfDocument = new HWPFDocument(fs);
关于HWPFDocument、POIFSFileSystem与DirectoryNode
上面提到了HWPFDocument、POIFSFileSystem与DirectoryNode这三个类,相信有人会因为它们的作用是什么感到疑惑,为什么需要它们,这里做个我了解后的简单介绍:
- HWPFDocument------承接文档内容(如你写在文档上的书写内容、内容被设置的样式)
- POIFSFileSystem-------承接文档信息(如文档属性)
- DirectoryNode-------承接文档目录某一节点
从官方例子中我们可以得知HWPFDocument的内容如何获取,下面是我写的如何获得文档内容与样式的例子代码,蹭了一下POIFSFileSystem:
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("src/main/resources/static/demo.doc"));
//使用POIFSFileSystem获得HWPFDocument对象
HWPFDocument hwpfDocument = new HWPFDocument(fs);
//获得内容对象(但此时的内容对象为全范围,因此不具备具体内容,仅仅是一个对象)
Range range = hwpfDocument.getRange();
//获得样式表
StyleSheet styleSheet = hwpfDocument.getStyleSheet();
//获得段落对象
Paragraph paragraph = range.getParagraph(1);
//获得具体某段落内容
String text = paragraph.text();
//获得具体某段落样式
StyleDescription styleDescription = styleSheet.getStyleDescription(paragraph.getStyleIndex());
System.out.println(text);
System.out.println(styleDescription.getName());
通过反复查阅与测试,我又尝试了使用POIFSFileSystem与DirectoryNode获得我们一般意义上的文档内容(即文档书写内容与样式):
//获得树根
DirectoryNode root = fs.getRoot();
//树根迭代器
Iterator<Entry> entries = root.getEntries();
//视图迭代器
Iterator<Object> viewableIterator = root.getViewableIterator();
while (viewableIterator.hasNext()){
Object next = viewableIterator.next();
if(next instanceof POIFSViewable){
POIFSViewable next1 = (POIFSViewable) next;
System.out.println(next1.getShortDescription());
}else {
System.out.println(next.toString());
}
}
System.out.println("=======================");
while (entries.hasNext()){
Entry next = entries.next();
if (next.isDocumentEntry()) {
DocumentEntry docEntry = (DocumentEntry) next;
System.out.println("Document entry: " + docEntry.getName());//文件对象
} else if (next.isDirectoryEntry()) {
DirectoryEntry dirEntry = (DirectoryEntry) next;
System.out.println("Directory entry: " + dirEntry.getName());//目录对象
HWPFDocument hwpfDocument = new HWPFDocument((DirectoryNode) next);
Range range = hwpfDocument.getRange();
Paragraph paragraph = range.getParagraph(0);
String text1 = paragraph.text();
System.out.println(text1);
}
}
我发现,将主导流设置为POIFSFileSystem后,无论我怎么操作都无法获取书写内容与样式。
关于三者的看法
一开始的利用POIFSFileSystem创建HWPFDocument,在我看来,本质只是流规则转变,是很常规的操作,并不能证明从POIFSFileSystem那也可以获得文档书写内容或样式,或证明获得节点对象DirectoryNode后再转成HWPFDocument可以获得文档书写内容/样式。输入流传入来后,你的决定会决定流往操作文档内容发展还是操作文档信息发展。
上面我使用了POIFSFileSystem的两个迭代器去迭代POIFSFileSystem对象拥有的列表,无论如何都只能得出文档信息,而得不到文档内容(不知道是我的doc文件内容问题,还是确实不能,欢迎指点)。同时,除了上述两个迭代器,POIFSFileSystem还有个getPropertyTable,也可以在获取对象后通过层层操作获得迭代器去迭代列表,但是,操作对象最后一样指向POIFSViewable,换言之,也就是操作结果和getViewableIterator后的操作结果没区别。
并且,各位应该可以看到我上面第二个迭代器的处理代码,我把类型判断都用上了,即同时用了isDocumentEntry()和isDirectoryEntry(),无论我怎么处理,都只有Document那一个判断通过,打印信息如下:
Document entry: WordDocument
Document entry: DocumentSummaryInformation
Document entry: SummaryInformation
Document entry: 1Table
Document entry: CompObj
Document entry: Data
Process finished with exit code 0
而两种迭代所获得的类子类如下:
只有DirectoryEntry可以转为DirectoryNode,我没法通过DocumentEntry使用构造方法HWPFDocument(DirectoryNode directory)。也即是说,即使我想通过POIFSFileSystem获得DirectoryNode也是没成功。那么,对于针对文档开发的操作代码来说,只使用HWPFDocument(java.io.InputStream istream)即可。