Flutter 三方库 charset_converter 的鸿蒙适配教程
Flutter 三方库 charset_converter 的鸿蒙适配教程
本文配套仓库:https://atomgit.com/oh-flutter/charset_converter(TAG:
2.4.0-ohos-1.0.0-beta.1,分支:feat/ohos_charset_converter_2.4.0)。本文解决的是另一件事:从上游 GitHub 仓库开始,把 charset_converter 完整适配到 OpenHarmony / HarmonyOS 平台,并在模拟器上验证。
charset_converter 是 pub.dev 上的一个字符集/编码转换 Flutter 插件(作者 pr0gramista,MIT 协议,2.4.0)。它的思路是把编码转换完全交给各平台自带的原生能力:Android 用 java.nio.charset.Charset,iOS/macOS 用 Core Foundation 的 CFString 转换,Linux 走 iconv,从而不引入任何第三方编解码依赖。Dart 内置的编解码器只有 UTF-8、Latin-1、ASCII 这几种,处理 GBK、Big5、Shift_JIS 这类遗留编码时,这个插件是常见的落地方案。
上游支持 Android、iOS、Linux、macOS、Windows,唯独没有鸿蒙。而鸿蒙侧 ArkTS 的 util.TextEncoder 只支持 UTF-8,覆盖不了其他字符集,所以本次适配在插件的 ohos 模块里实现了一个 C++ NAPI 原生模块,调用 OpenHarmony NDK 自带的 ICU4C(libicu.so 的 ucnv_* 系列接口)完成真实编解码。本文完整走一遍社区三方库适配的标准流程:把上游仓库同步到 AtomGit,拉到宿主机,建适配分支,用命令自动补全 ohos 目录,补全原生实现,补齐适配说明文件后提交分支与 TAG,最后用仓库自带的 example 在 DevEco 模拟器上验证。
一、环境搭建
鸿蒙 Flutter 开发环境(ohos 版 SDK、DevEco Studio、签名配置)的完整搭建步骤,官方指南已经写得很细,直接照做即可:
适配工作比单纯使用多一项要求:终端里 flutter 命令必须指向 ohos 版 SDK,因为后文自动补全 ohos 目录靠的是它提供的 flutter create --platforms ohos 能力。环境装好后用 flutter devices 确认能识别鸿蒙设备。本文实测使用的环境:
| 项 | 版本 |
|---|---|
| Flutter(ohos 版) | 3.41.10-ohos-1.0.1 |
| DevEco Studio | 26.0.0.821 |
| 编译 SDK | HarmonyOS 26.0.0(OpenHarmony API 26) |
| 实测设备 | DevEco 模拟器 emulator 7.0.0.105(OpenHarmony API 26) |
二、适配过程
2.1 将上游仓库同步到 AtomGit
鸿蒙 Flutter 三方库社区(oh-flutter 组织)托管在 AtomGit,上游项目在 GitHub,适配的第一步是把上游代码完整迁入 AtomGit 上为它新建的目标仓库 oh-flutter/charset_converter。做法是把上游克隆下来,添加 AtomGit 远端后整库推送,保留全部 commit 历史与 TAG,后续上游发新版时也能用同样的方式增量同步:
# 克隆上游仓库,目录名与目标仓库保持一致
git clone https://github.com/pr0gramista/charset_converter.git charset_converter
cd charset_converter
# 关联 AtomGit 目标仓库
git remote add atomgit https://atomgit.com/oh-flutter/charset_converter.git
# 推送全部分支与 TAG
git push atomgit --all
git push atomgit --tags
推送完成后,打开 AtomGit 上目标仓库的页面,能看到与上游一致的提交历史和源码目录:

图一:同步完成后 AtomGit 目标仓库的代码页
2.2 拉取代码到宿主机
从目标仓库把代码拉到本地,后续所有操作都在这份代码上进行:
git clone https://atomgit.com/oh-flutter/charset_converter.git
cd charset_converter
此时的目录是上游的原始结构。和 flutter_email_sender 那类 federated plugin(联邦插件)不同,charset_converter 上游是"单文件插件"——lib/ 下只有一个文件,全部 Dart API 都在 charset_converter.dart 里,import 的只有 dart:async、dart:convert、dart:io 和 flutter/services,没有任何内部平台接口层:
charset_converter/
├── android/ # Android 实现:java.nio.charset.Charset
├── ios/ # iOS/macOS 共用实现:CoreFoundation CFString(SwiftPM 组织)
│ └── charset_converter/Sources/charset_converter/CharsetConverterPlugin.swift
├── linux/ # Linux 实现:iconv
├── macos/
├── windows/
├── lib/
│ └── charset_converter.dart # 全部 Dart API:encode/decode/checkAvailability/availableCharsets
├── test/ # 上游单测
├── example/ # 上游自带示例
├── pubspec.yaml # version: 2.4.0
└── README.md
记住这个结构,2.3 节甄别 flutter create 的生成物时全靠它。
2.3 创建适配分支并补全 ohos 目录结构
先建适配分支。命名规则是 feat/ohos_<库名>_<版本号>,版本号取自上游 pubspec.yaml 的 version 字段(本库为 2.4.0):
git checkout -b feat/ohos_charset_converter_2.4.0
然后执行 ohos 版 SDK 提供的关键命令,它会读取 pubspec 中的插件声明,自动生成 ohos 宿主目录并追加插件注册节点:
flutter create --platforms ohos .
生成物中与插件直接相关的文件及各自职责:
| 文件 | 职责 |
|---|---|
ohos/index.ets | 模块入口,导出插件类供宿主引用 |
ohos/oh-package.json5 | 模块包描述,声明对 @ohos/flutter_ohos 的依赖 |
ohos/src/main/module.json5 | 模块配置 |
ohos/src/main/ets/components/plugin/CharsetConverterPlugin.ets | 插件模板:生命周期三接口 + 空 onMethodCall,2.4 节要补的就是它 |
ohos/build-profile.json5 | 模块构建配置,2.4 节要在这里接入 C++ 构建 |
有两点经验值得单独说明。第一,flutter create --template=plugin 的模板默认按 federated 插件组织,会在 lib/ 下额外生成 charset_converter_platform_interface.dart、charset_converter_method_channel.dart,在 test/ 下生成对应单测,还可能铺开 android/ios/linux/macos/web 的模板文件。本插件上游是单文件结构,lib/charset_converter.dart 不 import 任何内部文件,这些生成物可以对照 2.2 节的原始目录树全部清掉。清理时务必逐个核对上游原始文件清单,不要手滑删掉上游自己的文件——本次适配就误删过 windows/include 下的头文件,用 git restore 找回的。
第二,example 目录如果也要补 ohos 宿主,同样进入 example/ 执行一次 flutter create --platforms ohos .,模板会生成 example/ohos/ 宿主工程(含 EntryAbility、GeneratedPluginRegistrant 等注册链路)。
2.4 在插件文件中补全 ohos 实现
先看改动全景。本次适配遵循"只做加法"原则,原有平台实现一行不动:
| 文件 | 改动 |
|---|---|
ohos/src/main/cpp/charset_converter_napi.cpp | 新增:ICU4C 编解码的 C++ NAPI 实现 |
ohos/src/main/cpp/CMakeLists.txt | 新增:native 构建脚本,链接 libicu.so 与 libace_napi.z.so |
ohos/build-profile.json5 | 修改:externalNativeOptions 接入 CMake,abiFilters 加 arm64-v8a/x86_64 |
ohos/src/main/ets/components/plugin/CharsetConverterPlugin.ets | 修改:实现 ArkTS 桥接,注册 charset_converter 通道,四个方法分发到 NAPI |
lib/、android/、ios/ 等原有实现 | 一行不动 |
选型:为什么是 C++ NAPI。 鸿蒙 Flutter 插件的惯例是 ArkTS 实现 MethodCallHandler,但 ArkTS 的 util.TextEncoder/util.TextDecoder 只支持 UTF-8,覆盖不了 GBK、Big5、Shift_JIS 这些字符集。而系统层面有现成的 ICU4C:OpenHarmony NDK 提供合并版的 libicu.so,ucnv_* 正是各平台 ICU 通用的那套 C API。因此本次方案是 ArkTS 只做桥接,真正的转换放在 C++,链路为 Dart → MethodChannel → ArkTS → NAPI → ICU4C。这样既不引入三方依赖,也不用往包里塞 ICU 数据(系统自带,实测 232 个字符集可用)。
Dart 侧为什么零改动。 上游四个接口全部走同一个 MethodChannel('charset_converter'),通道名没有平台前缀,鸿蒙侧插件注册到同名通道即可被引擎正确路由。代码里唯一的平台分支是 Platform.isLinux(为 iconv 的 C 字符串补 '\0' 结尾),鸿蒙的 encode 参数直接传 String,天然走 else 分支。这正是"只做加法"的理想形态:所有平台差异吸收在原生层,Dart 接口对使用方完全一致。
ArkTS 侧的插件实现(CharsetConverterPlugin.ets):
import {
FlutterPlugin, FlutterPluginBinding, MethodCall,
MethodCallHandler, MethodChannel, MethodResult,
} from '@ohos/flutter_ohos';
// NAPI 模块:.so 文件名 = lib + nm_modname + .so
import charsetNative from 'libcharset_converter_ohos.so';
export default class CharsetConverterPlugin implements FlutterPlugin, MethodCallHandler {
private channel: MethodChannel | null = null;
onAttachedToEngine(binding: FlutterPluginBinding): void {
// 与上游 Dart 侧使用完全相同的通道名
this.channel = new MethodChannel(binding.getBinaryMessenger(), 'charset_converter');
this.channel.setMethodCallHandler(this);
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
if (this.channel != null) {
this.channel.setMethodCallHandler(null);
}
}
onMethodCall(call: MethodCall, result: MethodResult): void {
switch (call.method) {
case 'encode': {
const charset: string = call.argument('charset') as string;
const data: string = call.argument('data') as string;
try {
const bytes: ArrayBuffer = charsetNative.charsetEncode(charset, data);
result.success(new Uint8Array(bytes));
} catch (e) {
result.error('CharsetConversionError', `${e}`, null);
}
break;
}
case 'decode': {
const charset: string = call.argument('charset') as string;
const data: Uint8Array = call.argument('data') as Uint8Array;
try {
// 传给 native 前做一次精确切片,避免 byteOffset 不为 0 时多带数据
const buffer: ArrayBuffer =
data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;
const text: string = charsetNative.charsetDecode(charset, buffer);
result.success(text);
} catch (e) {
result.error('CharsetConversionError', `${e}`, null);
}
break;
}
case 'check': {
const charset: string = call.argument('charset') as string;
try {
result.success(charsetNative.charsetCheck(charset) as boolean);
} catch (e) {
result.error('CharsetConversionError', `${e}`, null);
}
break;
}
case 'availableCharsets': {
try {
const list: Array<string> = charsetNative.charsetAvailable() as Array<string>;
result.success(list);
} catch (e) {
result.error('CharsetConversionError', `${e}`, null);
}
break;
}
default:
result.notImplemented();
}
}
}
几个关键点:四个方法名 encode/decode/check/availableCharsets 与上游 Dart 侧 invokeMethod 的方法名一一对应;每个分支都是 try/catch 里恰好一次回复(成功 result.success,失败 result.error),保证 MethodResult 不会被回复两次;失败统一抛 CharsetConversionError 错误码,Dart 侧收到的是 PlatformException,与 Android 侧 Charset.forName 抛异常经通道转成 PlatformException 的行为对齐。
C++ 侧的核心是任意两个字符集之间的转换函数(charset_converter_napi.cpp):
bool ConvertBytes(const char* toCharset, const char* fromCharset,
const char* src, size_t srcLen,
std::vector<char>& out, std::string& err) {
UErrorCode status = U_ZERO_ERROR;
UConverter* targetCnv = ucnv_open(toCharset, &status);
if (U_FAILURE(status)) { err = u_errorName(status); return false; }
UConverter* sourceCnv = ucnv_open(fromCharset, &status);
if (U_FAILURE(status)) { ucnv_close(targetCnv); err = u_errorName(status); return false; }
bool ok = false;
std::vector<UChar> pivot(kPivotSize); // 1024 个 UChar 的 UTF-16 枢纽缓冲
size_t capacity = (srcLen < kMinOutCapacity) ? kMinOutCapacity : srcLen * 2 + 16;
for (int attempt = 0; attempt < 6 && !ok; ++attempt) {
out.resize(capacity);
char* target = out.data();
char* targetLimit = target + capacity;
const char* source = src;
const char* sourceLimit = src + srcLen;
UChar* pivotStart = pivot.data();
UChar* pivotSource = pivotStart;
UChar* pivotTarget = pivotStart;
UChar* pivotLimit = pivotStart + kPivotSize;
status = U_ZERO_ERROR;
ucnv_convertEx(targetCnv, sourceCnv, &target, targetLimit,
&source, sourceLimit,
pivotStart, &pivotSource, &pivotTarget, pivotLimit,
TRUE, TRUE, &status);
if (status == U_BUFFER_OVERFLOW_ERROR) { capacity *= 2; continue; }
if (U_FAILURE(status)) { err = u_errorName(status); break; }
out.resize(static_cast<size_t>(target - out.data()));
ok = true;
}
ucnv_close(targetCnv);
ucnv_close(sourceCnv);
if (!ok && err.empty()) { err = "U_BUFFER_OVERFLOW"; }
return ok;
}
ucnv_convertEx 通过一块 UTF-16 pivot 缓冲在任意两个字符集间转换,输出缓冲不够时返回 U_BUFFER_OVERFLOW_ERROR,这里容量翻倍重试(上限 6 次)。在此基础上导出四个 NAPI 函数:charsetEncode(UTF-8 → 目标字符集,结果装进 napi_create_arraybuffer)、charsetDecode(目标字符集 → UTF-8,napi_create_string_utf8 返回)、charsetCheck(ucnv_open 成功即可用,ICU 会自动解析 gb2312、cp1252 这类别名)、charsetAvailable(ucnv_countAvailable + ucnv_getAvailableName 枚举全部规范名)。失败路径统一 napi_throw_error 抛出,错误消息用 u_errorName 转成的 ICU 错误名(如 U_FILE_ACCESS_ERROR),ArkTS 侧 catch 后原样透传给 Dart,排错时可以直接拿错误名查 ICU 文档。
C++ 模块通过 ohos/build-profile.json5 的 externalNativeOptions 接入 hvigor 构建:
"buildOption": {
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "",
"cppFlags": "",
"abiFilters": ["arm64-v8a", "x86_64"]
}
}
CMakeLists.txt 里把系统库直接链进来,无需在工程里放任何预编译产物:
add_library(charset_converter_ohos SHARED charset_converter_napi.cpp)
# libicu.so:OpenHarmony NDK 自带的合并版 ICU4C(提供 ucnv_* 转换接口)
# libace_napi.z.so:NAPI 运行时
target_link_libraries(charset_converter_ohos PUBLIC libace_napi.z.so libicu.so)
构建产物 libcharset_converter_ohos.so 会随插件自动打进 HAP 的 libs/arm64-v8a/ 与 libs/x86_64/ 目录,可以解包 HAP 确认。模块注册通过 napi_module 结构完成,nm_modname 必须叫 charset_converter_ohos——ArkTS 侧 import charsetNative from 'libcharset_converter_ohos.so' 的文件名正是由它决定的,两边对不上运行时就会报模块不存在。
2.5 补全适配说明文件并提交分支
四份适配说明文件各自的作用:
| 文件 | 作用 |
|---|---|
README.OpenSource | 开源软件申报信息:名称、协议、版本、上游地址 |
README.OpenHarmony_CN.md | 中文说明:简介、下载安装、兼容性、接口说明、遗留问题 |
README.OpenHarmony.md | 英文说明,内容与中文版对应 |
CHANGELOG.OpenHarmony.md | 鸿蒙适配版本变更记录,TAG 之间变更的唯一事实来源 |
README.OpenSource 的实际内容(JSON 数组格式):
[
{
"Name": "charset_converter",
"License": "MIT License",
"License File": "LICENSE",
"Version Number": "2.4.0",
"Owner": "qiaomu8559968@126.com",
"Upstream URL": "https://github.com/pr0gramista/charset_converter",
"Description": "Charset/encoding converter that uses underlying platform - no external dependencies. Adapted for the OpenHarmony platform with an ICU-based native implementation."
}
]
CHANGELOG.OpenHarmony.md 的实际内容:
## 2.4.0-ohos-1.0.0-beta.1
* Adapted charset_converter 2.4.0 for the OpenHarmony platform, implementing encode/decode/checkAvailability/availableCharsets on top of the system ICU4C library (libicu.so) through a NAPI native module.
* ArkTS `util.TextEncoder` only supports UTF-8, so the charset conversion is done in C++ (`ucnv_*` APIs) inside the plugin's ohos module; no third-party dependency is introduced.
* Added an OpenHarmony example demonstrating round-trip conversion for GBK/GB18030/Big5/Shift_JIS/EUC-KR/ISO-8859-*/windows-1252/KOI8-R/EUC-JP, charset availability checks, and error handling for unsupported charsets.
提交时注意一件事:如果构建过程中在 example/ohos/build-profile.json5 里配过签名,提交前要把它还原成空的 signingConfigs: [],签名材料属于本机隐私,一律不入库(构建时由 DevEco 或本地配置注入)。
git add -A
git commit -m "feat: adapt charset_converter for the OpenHarmony platform"
git push atomgit feat/ohos_charset_converter_2.4.0
# TAG 命名规则:原库版本-ohos-适配版本-beta.x(首个适配版 x=1)
git tag 2.4.0-ohos-1.0.0-beta.1
git push atomgit 2.4.0-ohos-1.0.0-beta.1
推送完成后在 AtomGit 仓库页面切换到分支与标签视图,能看到适配分支和 TAG:


图二:AtomGit 仓库页面的分支与 TAG
三、在 Demo 中验证适配效果
3.1 使用仓库自带的 example
优先改造仓库自带的 example/(path 依赖本地插件)。本次把上游的简单演示页改造成一个自动验证套件,启动即跑完 13 项用例:availableCharsets 统计、checkAvailability 五项判定、10 组字符集 round-trip(GBK、GB18030、Big5、Shift_JIS、EUC-KR、ISO-8859-1、ISO-8859-15、windows-1252、KOI8-R、EUC-JP),以及错误处理(不支持的字符集必须抛异常)。example 的 ohos 宿主由 flutter create 生成,包名 com.example.demo。
构建、安装、启动的完整命令:
cd example
flutter pub get
flutter build hap --debug
# 安装并启动(先用 hdc list targets 确认设备在线)
hdc install -r build/ohos/hap/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.example.demo
如果首次构建只产出 intermediates 没有 HAP,是签名未配置:用 DevEco Studio 打开 example/ohos,在 File > Project Structure > Signing Configs 勾选 Automatically generate signature,之后重新 flutter build hap 即可。
启动后应用自动执行全部用例,顶部统计卡显示 availableCharsets 返回 232 个字符集,checkAvailability 对 utf-8、GBK、Big5、ISO-8859-1 判 true、对不存在的 no-such-charset 判 false:

图三:example 启动即自动跑完 13 项验证,主界面为结果列表
3.2 自建工程时以 AtomGit 链接方式引入
自建工程推荐用 git 依赖并锁定 TAG,保证团队所有人拿到的适配版本一致:
dependencies:
charset_converter:
git:
url: https://atomgit.com/oh-flutter/charset_converter.git
ref: 2.4.0-ohos-1.0.0-beta.1
TAG 与框架版本对照:
| Flutter 框架版本 | TAG 名称 | 分支名 |
|---|---|---|
| 3.41 | 2.4.0-ohos-1.0.0-beta.1 | feat/ohos_charset_converter_2.4.0 |
兼容性说明:以上 TAG 在 stable 引擎(3.41.10-ohos-1.0.1)上实测通过;若使用 canary 引擎,宿主工程的 compatibleSdkVersion 需按引擎要求调整到 API 26。
3.3 调用接口并观察运行效果
最小调用代码就三行:
final Uint8List encoded = await CharsetConverter.encode('GBK', '你好,世界');
// encoded => [0xC4, 0xE3, 0xBA, 0xC3, ...]
final String decoded = await CharsetConverter.decode('GBK', encoded);
// decoded => '你好,世界'
验证页对 10 组字符集逐个做 encode → decode 回环比对,解码结果与原文一致才算 PASS。中日韩部分:

图四:GBK、GB18030、Big5、Shift_JIS、EUC-KR round-trip 全部 PASS,GB18030 用例包含 GBK 编不了的生僻字与 emoji
西欧与俄文字符集部分:

图五:ISO-8859-1、ISO-8859-15(含欧元符号)、windows-1252(智能引号与破折号)、KOI8-R 全部 PASS
后续的俄文与日文 EUC 用例:

图六:KOI8-R 与 EUC-JP round-trip PASS,HEX 列可看到多字节编码的实际字节序
错误处理用例:对不存在的字符集 definitely-not-a-charset 调用 encode,预期必须抛异常且不能让应用崩溃:

图七:不支持的字符集正确抛出 CharsetConversionError(PlatformException),消息为 ICU 错误名
适配完成度的客观总结:13 项用例全部 PASS;四个接口 encode/decode/checkAvailability/availableCharsets 全链路可用,返回值类型与语义和其他平台一致;差异点有两处——可用字符集数量由各平台 ICU 数据裁剪决定(本环境 232 个,与其他平台数量不同属正常差异),以及目标字符集编不了的字符 ICU 默认以替换字符填充(上游 Linux 的 iconv 是直接报错),极端场景建议用 round-trip 校验兜底。
四、常见问题
4.1 适配过程中的问题
Q1:flutter create --platforms ohos . 会不会破坏现有工程?
它只做加法:生成 ohos/ 目录并在 pubspec 声明的插件结构上追加注册节点。真正的风险是模板副作用——federated 模板会在 lib/、test/ 和各平台目录铺出与上游结构冲突的文件。做法是先记录上游原始文件清单(2.2 节的目录树),生成后逐项对照,把模板多出来的文件删掉。删之前用 git status 分清哪些是上游 tracked 文件,误删 tracked 文件用 git restore <路径> 找回。
Q2:为什么不直接用 ArkTS 的 util.TextEncoder 实现?
它只支持 UTF-8 一种编码,连 GBK 都编不了,无法覆盖插件的核心场景。系统自带的 ICU4C(NDK 的 libicu.so)才是正确工具,ucnv_* 与 Android 侧 ICU、Linux 侧 iconv 属于同一能力层级。
Q3:C++ 模块怎么接入 hvigor 构建?
在插件 ohos 模块的 build-profile.json5 加 externalNativeOptions(见 2.4 节),path 指向 CMakeLists.txt,abiFilters 按需填 arm64-v8a/x86_64。构建时 hvigor 调 CMake 出 .so,自动打进 HAP 的 libs/<abi>/。验证方法:解包 HAP 确认 libcharset_converter_ohos.so 存在于目标 ABI 目录。
Q4:构建通过,运行时报模块不存在或 charsetNative 未定义?
按顺序查三处:.so 是否真的进了 HAP(解包看 libs/);napi_module 的 nm_modname 是否为 charset_converter_ohos(ArkTS 的 import 文件名 libcharset_converter_ohos.so 由它决定);CMake 的 target_link_libraries 是否链了 libace_napi.z.so。另外插件注册在构建期完成,改过注册链路后必须全量重新构建,热重载验证不出来。
Q5:签名配置要不要提交?
不要。build-profile.json5 的 signingConfigs 含证书路径与本机加密口令,属本机隐私且可在 DevEco 里重新生成,提交前还原为空数组加注释说明(skill 的 N11 红线)。构建时通过 DevEco 自动签名或本地临时注入解决。
Q6:compatibleSdkVersion 怎么填?
本适配 example 的 ohos 宿主保持模板默认值(API 18 系)即可在 API 26 模拟器上运行,系统向下兼容;若使用 canary 引擎,宿主 compatibleSdkVersion 需要提到 API 26。插件侧不设额外要求,跟随宿主。
4.2 使用过程中的问题
Q1:传入不支持的字符集名会怎样?
encode/decode 会抛 PlatformException(code 为 CharsetConversionError),消息里带 ICU 错误名(如 U_FILE_ACCESS_ERROR)。这个错误名是 ICU 对"打不开该转换器"的标准返回,与文件权限无关,本质是字符集名不被支持。接入了别名机制,utf-8、cp1252、gb2312 这类别名都能直接用;不确定时先调 checkAvailability 探测。
Q2:availableCharsets 的数量和 Android 上不一样?
数量由各平台 ICU 数据裁剪决定,本环境 232 个,Android 设备上通常是另一个数。这是上游本来就存在的平台差异,业务代码不要对数量做断言,只用它做展示或探测。
Q3:目标字符集编不了的字符(如 GBK 编 emoji)怎么处理?
ICU 默认以替换字符填充而不是报错,和上游 Linux 平台 iconv 直接报错的行为不同。需要严格校验的场景,encode 之后 decode 回来与原文比对,不一致就换 GB18030 或报错给用户。
Q4:decode 出来是乱码但不报错?
字节序列与字符集不匹配时 ICU 会尽力转换,不会替你判断"编错了"。先确认数据来源的编码声明是否正确,用 checkAvailability 排除拼写问题,必要时做 round-trip 验证。
五、结语
本次适配把 charset_converter 的四个接口完整带到了 OpenHarmony:ArkTS 桥接 + C++ NAPI 调系统 ICU4C,Dart 层零改动,example 13 项验证全部通过。仓库托管在 oh-flutter/charset_converter,适配层问题请到鸿蒙仓库 Issue 反馈,原库行为问题请到上游 Issue 反馈。接入方式、接口用法与业务实战,见姊妹篇《charset_converter 的鸿蒙使用指南》。
六、相关链接
欢迎加入 CPF-Flutter 鸿蒙社区,社区入口、环境搭建指南和本文相关链接统一放在这里:
- CPF-Flutter 鸿蒙社区
- Flutter OHOS 开发环境搭建指南
- 鸿蒙版仓库
- 本文 TAG(分支
feat/ohos_charset_converter_2.4.0) - example 源码目录
- 上游仓库
- pub.dev 包页
更多推荐



所有评论(0)