详细代码:https://github.com/cxcn/dtool

前言

.uwl 是紫光拼音输入法(现在叫华宇拼音输入法)使用的词库。

解析

紫光的词库有点复杂,拼音用的索引,但是拼音表没有写在词库里。

好在深蓝词库转换工具已经解析好了,这部分就跳过了。

词长和拼音长关系密切,要注意。

主要词库部分每 1024 字节为一段(分段意义何在?)

前两个字节未知,第 3 个字节表示字符编码格式 0x08 是 GBK,0x09 是 UTF-16LE。

范围 描述
0x04 - 0x23 词库名
0x24 - 0x43 词库作者
0x44 - 0x47 词条数
0x48 - 0x4B 分为几段

0x4C - 0xBFF 未知。

从 0xC00 开始,每 1024 为一段,一段有个 16 字节的头信息。

4 个字节为一组,分别表示:第几段,未知,未知,词条占用字节数(小于 1024-16)。

占用字节数 描述
a 1 词占用字节 + 1(所以总是奇数),可能大于 0x80
b 1 拼音长度的一半,前 4 位(总是偶数)意义不明
2 词频
b%0x10*2 + a/0x80 拼音索引
a%0x80 - 1

代码实现:

var uwlSm = []string{
"", "b", "c", "ch", "d", "f", "g", "h", "j", "k", "l", "m", "n",
"p", "q", "r", "s", "sh", "t", "w", "x", "y", "z", "zh",
} var uwlYm = []string{
"ang", "a", "ai", "an", "ang", "ao", "e", "ei", "en", "eng", "er",
"i", "ia", "ian", "iang", "iao", "ie", "in", "ing", "iong", "iu",
"o", "ong", "ou", "u",
"ua", "uai", "uan", "uang", "ue", "ui", "un", "uo", "v",
} func (ZiguangUwl) Parse(filename string) Dict {
data, _ := os.ReadFile(filename)
r := bytes.NewReader(data)
ret := make(Dict, 0, r.Len()>>8)
r.Seek(2, 0)
// 编码格式,08 为 GBK,09 为 UTF-16LE
encoding, _ := r.ReadByte() // 分段
r.Seek(0x48, 0)
partLen := ReadUint32(r)
for i := 0; i < partLen; i++ {
r.Seek(0xC00+int64(i)<<10, 0)
ret = parseZgUwlPart(r, ret, encoding)
} return ret
} func parseZgUwlPart(r *bytes.Reader, ret Dict, e byte) Dict {
r.Seek(12, 1)
// 词条占用字节数
max := ReadUint32(r)
// 当前字节
curr := 0
for curr < max {
head := make([]byte, 4)
r.Read(head)
// 词长 * 2
wordLen := head[0]%0x80 - 1
// 拼音长
codeLen := head[1]<<4>>4*2 + head[0]/0x80
// 频率
freq := BytesToInt(head[2:])
// fmt.Println(freqSli, freq)
curr += int(4 + wordLen + codeLen*2) // 拼音
code := make([]string, 0, codeLen)
for i := 0; i < int(codeLen); i++ {
bsm, _ := r.ReadByte()
bym, _ := r.ReadByte()
smIdx := bsm & 0x1F
ymIdx := (bsm >> 5) + (bym << 3)
// fmt.Println(bsm, bym, smIdx, ymIdx)
if bym >= 0x10 || smIdx >= 24 || ymIdx >= 34 {
break
}
code = append(code, uwlSm[smIdx]+uwlYm[ymIdx])
// fmt.Println(smIdx, ymIdx, uwlSm[smIdx]+uwlYm[ymIdx])
} // 词
tmp := make([]byte, wordLen)
r.Read(tmp)
var word string
switch e {
case 0x08:
word, _ = util.Decode(tmp, "GBK")
case 0x09:
word, _ = util.Decode(tmp, "UTF-16LE")
}
// fmt.Println(string(word))
ret = append(ret, Entry{word, code, freq})
}
return ret
}

参考资料:

深蓝词库转换

输入法词库解析(三)紫光拼音词库.uwl的更多相关文章

  1. 开源 JSON 库解析性能对比( Jackson / Json.simple / Gson )

    Json 已成为当前服务器与 web 应用之间数据传输的公认标准. 微服务及分布式架构经常会使用 Json 来传输此类文件,因为这已经是 webAPI 的事实标准. 不过正如许多我们习以为常的事情一样 ...

  2. python爬虫之urllib库(三)

    python爬虫之urllib库(三) urllib库 访问网页都是通过HTTP协议进行的,而HTTP协议是一种无状态的协议,即记不住来者何人.举个栗子,天猫上买东西,需要先登录天猫账号进入主页,再去 ...

  3. 输入法词库解析(四)百度分类词库.bdict(.bcd)

    前言 .bdict 是百度的分类词库格式,可以在 https://shurufa.baidu.com/dict 下载. 手机百度的分类词库格式 .bcd 是一样的,可以在 https://mime.b ...

  4. 输入法词库解析(二)搜狗拼音细胞词库.scel(.qcel)

    详细代码:https://github.com/cxcn/dtool 前言 .scel 是搜狗拼音输入法所使用的细胞词库格式,可以在 https://pinyin.sogou.com/dict/ 下载 ...

  5. 输入法词库解析(五)极点码表.mb

    详细代码:https://github.com/cxcn/dtool 前言 mb 是极点五笔的码表格式. 解析 偏移量 描述 0x00 版本信息 0x1B 码表介绍 0x11F 所用到的按键数 0x1 ...

  6. 使用adns库解析域名

    1. adns.adns-python库简介 adns库是一个可进行异步非阻塞解析域名的库,主要使用C语言编写,在linux平台下运行.使用adns库进行域名解析效率非常,著名的开源网络爬虫larbi ...

  7. 用jieba库统计文本词频及云词图的生成

    一.安装jieba库 :\>pip install jieba #或者 pip3 install jieba 二.jieba库解析 jieba库主要提供提供分词功能,可以辅助自定义分词词典. j ...

  8. [深入浅出Windows 10]QuickCharts图表控件库解析

    13.4 QuickCharts图表控件库解析     QuickCharts图表控件是Amcharts公司提供的一个开源的图表控件库,这个控件库支持WPF.Silverlight.和Windows等 ...

  9. Struts2的标签库(三)——控制标签

    Struts2的标签库(三) --控制标签 1.if/elseif/else标签 用于分支控制,取代JSP中的if语句,根据一个boolean(test属性的值)值判断是否进行下一步运算或者输出等. ...

随机推荐

  1. c# 怎样能写个sql的解析器

    c# 怎样能写个sql的解析器 本示例主要是讲明sql解析的原理,真实的源代码下查看 sql解析器源代码 详细示例DEMO 请查看demo代码 前言 阅读本文需要有一定正则表达式基础 正则表达式基础教 ...

  2. cookie、session、tooken

    一.cookie 的诞生 首先需要知道Http协议的无状态连接的,即这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的. 服务端,既不知道上一次请求和这一次请求的关联,也无法知道哪一个客户 ...

  3. Codeforces Round #791 (Div. 2) A-C

    Codeforces Round #791 (Div. 2) A-C A 题目 https://codeforces.com/contest/1679/problem/A 题解 思路 知识点:数学,暴 ...

  4. 【C++】学生管理系统

    [C++]学生管理系统 一道非常经典的C语言题目,用C++实现   题目如下: 输入功能:由键盘输入10个学生的学号.姓名.三科成绩,并计算出平均成绩和总成绩,然后将它存入文件stud.dat. 插入 ...

  5. javaWeb,web服务器

    一. 1.ASP 国内最早最流行的语言就是ASP:微软研发 在HTML中嵌套了VB脚本,ASP+COM(网页元素) 在ASP开发中,基本一个业务就有几千行代码,页面机器混乱 维护成本高 <h1& ...

  6. Hbase学习(三)过滤器 java API

    Hbase学习(三)过滤器 HBase 的基本 API,包括增.删.改.查等. 增.删都是相对简单的操作,与传统的 RDBMS 相比,这里的查询操作略显苍白,只能根据特性的行键进行查询(Get)或者根 ...

  7. c++小游戏--五子棋

    大家好,我是芝麻狐! 这是我自制的小游戏,目前仅支持devc++. 如果你没有c++软件, 请打开网站GDB online Debugger | Compiler - Code, Compile, R ...

  8. 聊聊 C++ 右值引用 和 移动构造函数

    一: 背景 最近在看 C++ 的右值引用和移动构造函数,感觉这东西一时半会还挺难理解的,可能是没踩过这方面的坑,所以没有那么大的深有体会,不管怎么说,这一篇我试着聊一下. 二: 右值引用 1. 它到底 ...

  9. 字符编码和字符集和编码引出的问题_FileReader读取GBK格式的文件

    字符编码 计算机中鵆的信息都是用二进制数表示的,而我们在屏幕上看到的数字.英文.标点符号.汉子等字符都是二进制数转换之后的结果.按照某种规则,将字符存储到计算机中,称为编码.反之,将存储在计算机中的二 ...

  10. Fibonacci Nim

    目录 题意 题解 相关 Ref 题意 [COCI2010-2011#4] HRPA 取石子,但是: 先手第一次可取任意多个石子 此外每次可取的石子的个数,至少为 \(1\) ,至多为上一轮对方所取个数 ...