关于Apache-POI的学习与工具类封装日志【2】----从官方例子代码Word2Forrest分析HWPFDocument构造方法

官方例子指的是

上一章内容:关于Apache-POI的学习与工具类封装日志【1】----如何从官方文档的信息中部署环境并进行初期测试

关于HWPFDocument

示例代码中使用了HWPFDocument,通过Apache-POI官网的api文档我们可以发现,关于这个类的描述是:

This class acts as the bucket that we throw all of the Word data structures into.

这个类可以作为word文档所有内容的接收类

 经过一层层深入,确认这个类的本质也是流,因为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)即可。

        

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会为您提供一个简单的 Apache POI 工具类的使用示例。 首先,您需要在您的项目中引入 Apache POI 的依赖包,如果您使用 Maven,可以在 `pom.xml` 文件中添加以下代码: ```xml <dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> </dependencies> ``` 接下来,我们可以创建一个简单的 Java 类来演示如何使用 Apache POI。 ```java import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelWriter { public static void main(String[] args) { XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("Sheet1"); // 创建第一行并填写数据 Row row = sheet.createRow(0); Cell cell1 = row.createCell(0); cell1.setCellValue("姓名"); Cell cell2 = row.createCell(1); cell2.setCellValue("年龄"); // 创建第二行并填写数据 Row row2 = sheet.createRow(1); Cell cell3 = row2.createCell(0); cell3.setCellValue("张三"); Cell cell4 = row2.createCell(1); cell4.setCellValue(20); // 将数据写入 Excel 文件 try { FileOutputStream outputStream = new FileOutputStream(new File("output.xlsx")); workbook.write(outputStream); workbook.close(); outputStream.close(); System.out.println("数据写入成功"); } catch (IOException e) { e.printStackTrace(); } } } ``` 以上代码将创建一个名为 `Sheet1` 的 Excel 表格,并在第一行填写了 `姓名` 和 `年龄` 字段,第二行填写了 `张三` 和 `20` 的数据。最后将数据写入名为 `output.xlsx` 的 Excel 文件中。 希望这个简单的示例能够帮助您了解 Apache POI 的使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值