更新记录
1.0.0(2026-10-30)
首个版本:六类乱码可疑点逐行定位(替换符/锟斤拷双重转码/单字节误读/生僻字扎堆/控制字符/丢字问号),同类型相邻命中合并计数;可疑度 0–100 分三档并给处置建议;编码探测走 BOM → 严格 UTF-8 试解 → GBK 三步并回传判断依据;丢字预扫按 CharsetEncoder.canEncode 逐字符判定,输出字符/次数/行号并按次数排序;转换按 from 解码、to 编码写出,同时落 .loss.csv 丢字清单;体检报告导出 CSV / 纯文本,UTF-8 带 BOM。UTS→Kotlin 编译通过(index.kt 1447 行、classes.dex 59,008 字节),98 项回归测试全部通过;真机未执行(测试机安全锁屏,未提供解锁口令),市场截图为 H5 渲染并标注示例数据。
平台兼容性
uni-app
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | × | × | √ | × | √ | × | × |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | - | × | - | × | × | × | × |
编码转换与丢字预检(乱码识别)
给对接老系统、导老报表的你:转码之前先体检。
老 ERP 导出 GBK、新系统只吃 UTF-8,直接转过去两种结果:要么整屏乱码(锟斤拷、烫烫烫),
要么静悄悄少了几个字(生僻名字、镕、昇、㈱)。第二种最坑——文件能打开、行数也对,
等你把数据导进财务系统、对完账才发现某个人名是空的。
这个插件把「转码」拆成三步,每一步都能看结果:
- 体检:这段文本现在是乱的还是好的?0–100 分,逐行指出可疑点;
- 预扫:转成目标编码会丢哪些字?字符、次数、行号,一次列清;
- 转换:确认没问题再写文件,转换结果和丢字清单一起交回。
给谁用
- 实施/运维:客户现场导出的 CSV 进不了新系统,先确认是乱码还是丢字;
- 财务/仓管:老进销存导月报,GBK 转 UTF-8 后金额没问题但客户名对不上;
- 开发:接口联调收到一堆
锟斤拷,需要快速判断是哪一段被双重转码; - 数据迁移:从历史系统批量导出,转码前先出一份「会丢什么」的清单给客户确认。
能做什么
| 能力 | 说明 |
|---|---|
| 乱码体检 | 六类可疑点:替换符 U+FFFD、锟斤拷 双重转码、单字节误读(ä 型)、生僻字扎堆、控制字符、连续问号 |
| 可疑度打分 | 0–100,三档结论:干净 / 可疑 / 已乱码,附一句该怎么处理 |
| 逐行定位 | 每条可疑点带行号与上下文片段,同一行相邻同类点自动合并计数,不刷屏 |
| 编码探测 | BOM 优先 → 严格 UTF-8 试解(非法字节即判失败)→ 退回 GBK,并说明按什么判断出来的 |
| 丢字预扫 | 逐字符问目标编码「你能表示吗」,列出字符 / 次数 / 行号,按出现次数排序 |
| 转换 | 按 from 解码、按 to 编码写出,默认再落一份 .loss.csv 丢字清单 |
| 报告导出 | 体检结果出 CSV(类型 / 行号 / 字符 / 片段 / 说明)或纯文本摘要,带 BOM,Excel 双击不乱码 |
快速接入
import { check, probe, loss, convert, exportReport } from '@/uni_modules/szhzy-encoding-guard'
// 1. 体检一个文件(不传 charset 就自己探)
const r = check({ path: '/storage/emulated/0/Download/客户台账.csv' })
// r.ok / r.score / r.verdict / r.charset / r.guess / r.suspects[]
if (r.score >= 50) {
// 已经乱了:别在这份文件上转码,回源头重导
console.log(r.advice)
}
// 2. 只想知道这是什么编码
const p = probe({ path: '/storage/emulated/0/Download/客户台账.csv' })
// p.charset = 'GBK',p.guess = 'UTF-8 解不通,按 GBK 读'
// 3. 转码前先看会丢什么
const l = loss({ path: p.path, from: p.charset, to: 'UTF-8' })
// l.total = 0 → 一个都不丢,放心转
// l.chars = [{ ch: '昇', count: 3, lines: [12, 40, 91] }, ...]
// 4. 确认后转换,丢字清单自动落盘
const c = convert({
path: '/storage/emulated/0/Download/客户台账.csv',
from: 'GBK',
to: 'UTF-8',
fileName: '客户台账-utf8.csv'
})
// c.path 新文件路径;c.losses 丢字清单(同时写了 客户台账-utf8.csv.loss.csv)
// 5. 体检报告导成 CSV 交给客户
exportReport({ path: '...', format: 'csv', fileName: '编码体检.csv' })
粘一段文本直接测(不用文件)
const r = check({ text: '鎴戜滑鏄庡ぉ绛炬? ' })
r.score // 分数高 → 这段是双重转码过的
r.suspects // [{ line: 1, kind: 'double', label: '双重转码', snippet: '...' }]
API
| 方法 | 入参 | 返回 |
|---|---|---|
check |
{ path } 或 { text, bom? },可加 charset、gap、maxSuspects |
{ ok, score, verdict, verdictText, advice, charset, guess, bytes, stats, suspects[] } |
probe |
{ path, charset? } |
{ ok, charset, guess, bom, bytes, sizeText, chars } |
loss |
{ text } 或 { path, from? },加 to(默认 GBK) |
{ ok, target, total, kinds, chars: [{ ch, count, lines[] }] } |
lossCsv |
{ text, to, delimiter? } |
{ ok, csv, total, kinds } |
convert |
{ path, from?, to, dir?, fileName?, writeLoss?, delimiter? } |
{ ok, path, fileName, bytes, sourceCharset, targetCharset, losses } |
exportReport |
{ path 或 text, format: 'txt'\|'csv', dir?, fileName?, bom? } |
{ ok, path, bytes, sizeText } |
charsets |
— | 支持清单(UTF-8 / GBK / GB18030 / UTF-16LE) |
getOutputDir |
— | 应用外部私有目录绝对路径 |
getVersion |
— | 版本号 |
所有方法返回统一信封 { ok, code, message, ... },不抛异常。
返回里的 stats
| 字段 | 含义 |
|---|---|
chars / lines / bytes |
字符数(UTF-16 单元)、行数、按 UTF-8 计的字节数 |
replaceCount |
U+FFFD 替换符个数——大于 0 说明有过不可逆的丢字 |
controlCount |
除 \t \r \n 外的控制字符个数 |
rareCount / rarePct |
生僻区汉字(CJK 扩展 A、兼容区)个数与占比(千分数) |
questionRuns |
连续 3 个以上问号出现的次数——通常是上一次转码丢字的残留 |
hasBom / nonBmp |
是否有 BOM、BMP 外字符(emoji、扩展 B 汉字)个数 |
判定规则是写死的,不是拍脑袋
| 可疑点 | 分值 | 依据 |
|---|---|---|
U+FFFD |
每个 10 分,最多 80 | 解码失败才会产生替换符,出现即已丢字 |
锟斤拷 |
每处 20 分,最多 40 | UTF-8 被当 GBK 读、再存回 UTF-8 的固定残渣 |
烫烫烫 / 屯屯屯 |
每处 25 分 | 未初始化内存被当字符串写出,导出端 bug |
| 单字节误读 | 每处 4 分,最多 20 | Ã Â ï 后跟非 ASCII,典型的「UTF-8 当单字节读」 |
| 生僻字扎堆 | 占比 ≥10% 加 15 分,≥25% 加 25 分 | 正常业务文本不会大段是扩展 A 区汉字 |
| 控制字符 | 每处 6 分,最多 18 | 粘贴进系统容易截断字段 |
| 连续问号 | 每处 4 分,最多 12 | 不可表示字符被换成 ? 的痕迹 |
合计上限 100:<20 干净、20–49 可疑、≥50 已乱码。
边界与限制
- 只处理纯文本。Word / Excel / PDF 请先用
szhzy-docx-read、szhzy-xlsx-import抽成文本再进来; - 编码探测只覆盖 UTF-8 / GBK / BOM 三条路。UTF-16(无 BOM)、Big5、Shift-JIS 认不出,
这时会明说「UTF-8 解不通,按 GBK 读」,请调用方显式传
from; - 丢字预扫按字符问
CharsetEncoder.canEncode,结果与 Java 的编码表完全一致, 但遇到「某些系统用私有区映射生僻字」的情况,预扫会说能表示、对方系统仍可能显示成方框; - 转码不修数据。已产生的
锟斤拷不可逆,插件只负责告诉你「这里有、在第几行」,不猜原字; - 单文件上限 20 MB(读字节保护),超过直接返回
READ_FAILED,请先切分。
平台
仅 Android(utssdk/app-android)。已用 UTS→Kotlin 编译通过,详见 接入示例.md 与 测试记录.md。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 13
赞赏 0
下载 12729937
赞赏 1959
赞赏
京公网安备:11010802035340号