前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

做移动端开发这些年,碰到过不少需要读取 Word 文档内容的需求——简历解析、合同预览、文档搜索。在 Android 上有 Apache POI 这种成熟的 Java 库可以用,但到了 OpenHarmony 上,情况完全不一样:没有现成的 Word 解析库,连一个能用的第三方包都找不到。

doc_text 这个 Flutter 插件做的事情很简单——给它一个 .doc.docx 文件路径,它返回一个纯文本字符串。听起来不复杂,但 OpenHarmony 端的实现写了 684 行纯 ArkTS 代码,其中包含一个完整的 OLE2 二进制格式解析器。这个适配过程本身就是一个很好的技术案例。

一、doc_text 插件简介

1.1 核心功能

import 'package:doc_text/doc_text.dart';

final String? text = await DocText().extractTextFromDoc('/path/to/document.docx');

一个方法,一个参数,一个返回值。API 设计极其简洁。

1.2 支持的格式

请添加图片描述

1.3 典型使用场景

  1. 简历解析:从用户上传的 Word 简历中提取文本,用于关键词匹配
  2. 文档搜索:建立文档内容索引,支持全文检索
  3. 内容预览:在不打开 Word 的情况下快速预览文档内容
  4. 数据迁移:批量提取旧系统中 Word 文档的文本内容

二、.doc 与 .docx 的本质区别

2.1 两种格式的对比

.doc 文件(Word 97-2003):
┌──────────────────────────────┐
│     OLE2 复合文档(二进制)     │
│  ┌──────────────────────┐    │
│  │ WordDocument 流       │    │
│  │ (二进制文本数据)       │    │
│  ├──────────────────────┤    │
│  │ 1Table / 0Table 流    │    │
│  │ (格式信息)            │    │
│  ├──────────────────────┤    │
│  │ 其他流...             │    │
│  └──────────────────────┘    │
└──────────────────────────────┘

.docx 文件(Word 2007+):
┌──────────────────────────────┐
│     ZIP 压缩包               │
│  ├── [Content_Types].xml     │
│  ├── _rels/.rels             │
│  ├── word/                   │
│  │   ├── document.xml  ←关键  │
│  │   ├── styles.xml          │
│  │   └── ...                 │
│  └── docProps/               │
└──────────────────────────────┘

2.2 解析难度对比

维度 .doc .docx
格式类型 二进制 文本(XML)
解析难度 极高 中等
需要的知识 OLE2、FAT、Piece Table ZIP、XML
代码量(本插件) ~500 行 ~100 行
第三方库依赖 无(手写) zlib(系统自带)

💡 解析 .doc 的难度大约是 .docx 的 5-10 倍。.docx 本质上就是个 ZIP 包,解压后读 XML 就行。而 .doc 是微软 1997 年设计的二进制格式,需要理解扇区、FAT 表、Piece Table 等底层概念。

三、各平台实现策略

3.1 Android 端

// Android 使用 Apache POI 库
val doc = HWPFDocument(FileInputStream(filePath))  // .doc
val text = doc.text.toString()

val docx = XWPFDocument(FileInputStream(filePath))  // .docx
val text = XWPFExtractor(docx).text

Android 端直接依赖 Apache POI——Java 生态中最成熟的 Office 文档处理库。优点是功能强大,缺点是包体积大(POI 全量引入可以增加好几 MB)。

3.2 OpenHarmony 端

// OpenHarmony 端:纯 ArkTS 手写实现
export default class DocTextPlugin implements FlutterPlugin, MethodCallHandler {
  // 684 行代码,包含:
  // - .docx 解析:ZIP 解压 + XML 正则提取
  // - .doc 解析:OLE2Parser 手写解析器
  // - 字符编码处理:Unicode / ANSI 双模式
  // - 文本清洗:控制字符过滤 + 换行统一
}

OpenHarmony 端没有 Apache POI 可用,所以一切从零开始。这是整个适配中最有挑战的部分。

3.3 iOS 端

iOS 端:目前功能有限
由于 iOS 原生对 .doc/.docx 格式的支持有限,
当前版本在 iOS 上的功能受到限制。

3.4 平台实现对比

平台 实现方式 代码量 依赖
Android Apache POI ~50 行 poi-ooxml(大)
OpenHarmony 纯 ArkTS 手写 684 行 无外部依赖
iOS 有限支持 - -

四、OpenHarmony 适配的独特挑战

4.1 没有现成的 Word 解析库

这是最大的挑战。Android 有 Apache POI,Java 有 docx4j,Python 有 python-docx,但 ArkTS/OpenHarmony 生态中没有任何 Word 文档解析库

4.2 必须手写 OLE2 解析器

OLE2 复合文档格式(Compound Binary File Format):
- 微软 1997 年设计的二进制存储格式
- 被 .doc / .xls / .ppt 等 Office 97-2003 格式使用
- 内部结构类似一个迷你文件系统
- 有扇区、FAT 表、目录流等概念
- 官方文档 200+ 页

在 OpenHarmony 上解析 .doc 文件,意味着要从零实现一个 OLE2 解析器。这不是简单的字符串处理,而是真正的二进制格式逆向工程

4.3 字符编码的复杂性

Word 文档中的文本可能是:
- Unicode(UTF-16LE):现代文档
- ANSI(CP1252 / GBK):旧文档
- 混合编码:同一文档中两种编码混用

需要根据 Piece Table 中的标志位来判断每一段文本的编码。

4.4 没有 XML 解析库

// OpenHarmony 虽然有 @ohos.xml 模块,但实际使用中
// 对 OOXML 的命名空间处理不够友好
// 所以 .docx 的 XML 解析也是用正则实现的

const textRegex = /<w:t[^>]*>([^<]*)<\/w:t>/g;

📌 doc_text 的 OpenHarmony 实现是一个"零依赖"方案——不依赖任何第三方库,所有解析逻辑都是手写的。这在 Flutter 插件适配中是比较少见的。

五、插件架构概览

5.1 整体架构

┌─────────────────────────────────────┐
│           Dart 层                    │
│  DocText → DocTextPlatform           │
│         → MethodChannelDocText       │
│         → MethodChannel('doc_text')  │
└──────────────┬──────────────────────┘
               │ invokeMethod('extractTextFromDoc')
┌──────────────┴──────────────────────┐
│         原生层(OpenHarmony)         │
│  DocTextPlugin                       │
│  ├── extractTextFromDocx()  (.docx)  │
│  │   ├── fs.openSync / readSync      │
│  │   ├── zlib.decompressFile         │
│  │   └── parseDocxXml (正则)          │
│  └── extractTextFromOldDoc() (.doc)  │
│      ├── OLE2Parser                  │
│      │   ├── readFAT                 │
│      │   ├── readMiniFAT             │
│      │   └── readStream              │
│      ├── extractWordText             │
│      │   ├── FIB 解析                │
│      │   └── Piece Table 提取        │
│      └── extractTextDirect (回退)     │
└──────────────────────────────────────┘

5.2 代码分布

模块 行数 占比 复杂度
DocTextPlugin 主类 ~180 行 26%
.docx 解析 ~70 行 10%
.doc 文本提取 ~230 行 34%
OLE2Parser ~200 行 29% 极高
DirectoryEntry 接口 ~6 行 1%

六、与其他适配插件的对比

6.1 三个插件的适配特点

维度 doc_text flutter_web_auth secure_application
核心功能 文档解析 Web 认证 内容保护
需要 AbilityAware
需要宿主集成
原生代码量 684 行 161 行 234 行
外部依赖
核心难点 二进制格式解析 深度链接 窗口安全标志

6.2 doc_text 的独特之处

  • 代码量最大:684 行,是 flutter_web_auth 的 4 倍多
  • 纯计算型:不涉及系统 UI、网络、Ability 等系统能力
  • 零外部依赖:所有解析逻辑手写
  • 二进制处理:大量的字节级操作(readU16、readU32、位运算)

七、本系列文章规划

7.1 内容路线

  1. 基础篇(第1-2篇):插件概览、Word 文档格式科普
  2. 架构篇(第3-7篇):Dart 层、Android 端、OpenHarmony 工程搭建、接口实现
  3. docx 解析篇(第8-10篇):格式路由、ZIP 解压、XML 正则提取
  4. doc 解析篇(第11-16篇):OLE2 格式、OLE2Parser、目录解析、FIB、Piece Table、回退策略
  5. 工程篇(第17-20篇):字符处理、临时文件、错误处理、总结展望

7.2 阅读建议

  • 如果你只关心 docx 解析,看第 8-10 篇就够了
  • 如果你对 二进制格式解析 感兴趣,第 11-16 篇是重头戏
  • 如果你想 快速上手适配,先看第 5-7 篇的工程搭建部分

总结

doc_text 是一个功能简单但实现复杂的 Flutter 插件。它的 OpenHarmony 适配有三个特点:

  1. 零依赖:没有使用任何第三方 Word 解析库
  2. 手写 OLE2 解析器:684 行纯 ArkTS 代码实现完整的二进制格式解析
  3. 双格式支持:.doc(OLE2)和 .docx(ZIP+XML)两种格式都能处理

下一篇我们从 Word 文档格式本身讲起——理解了格式,才能理解代码。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

doc_text 演示
doc_text 插件文档解析演示

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐