输入法词库解析(七)微软用户自定义短语.dat
前言
微软拼音和微软五笔通用的用户自定义短语 dat 格式。
解析
前 8 个字节标识文件格式 machxudp,微软五笔的 lex 格式是 imscwubi。
下面 8 个字节应该是版本号。
接下来每 4 字节一组,分别表示偏移表开始、词条开始、文件总长、词条数、导出的时间戳。
然后补 0 一直到偏移表开始。
偏移表记录了每个词条从词条开始的偏移量,每 4 个字节一组。
接下来就是词条本体部分:
| # | 占用字节数 | 描述 |
|---|---|---|
| 4 | 10 00 10 00 标记 |
|
| a | 2 | 该词条总字节长 - 词占用的字节长 |
| 1 | 在候选中的位置 | |
| 1 | 0x06或0x13,未知 |
|
| 4 | 0 | |
| 4 | 从2010-01-01开始的时间戳 |
|
| a - 16 | 编码(utf-16le),00 标识结束 | |
| 词条总字节长 - a | 词(utf-16le),00 标识结束 |
代码实现:
func (MsUDP) Parse(filename string) Table {
data, _ := os.ReadFile(filename)
r := bytes.NewReader(data)
ret := make(Table, 0, r.Len()>>8)
// 词库偏移量
r.Seek(0x10, 0)
offset_start := ReadUint32(r) // 偏移表开始
entry_start := ReadUint32(r) // 词条开始
entry_end := ReadUint32(r) // 词条结束
entry_count := ReadUint32(r) // 词条数
export_time := ReadUint32(r) // 导出的时间
t := time.Unix(int64(export_time), 0)
fmt.Println(t, entry_end)
// 第一个偏移量
offset := 0
for i := 0; i < entry_count; i++ {
var next, length int
if i == entry_count-1 {
length = entry_end - entry_start - offset
} else {
r.Seek(int64(offset_start+4*(i+1)), 0)
next = ReadUint32(r)
length = next - offset
}
// fmt.Println(offset, next, length)
r.Seek(int64(offset+entry_start), 0)
offset = next
ReadUint32(r) // 0x10001000
codeLen := ReadUint16(r) // 编码字节长+0x12
order, _ := r.ReadByte() // 顺序
_, _ = r.ReadByte() // 0x06 不明
ReadUint32(r) // 4 个空字节
ReadUint32(r) // 时间戳
tmp := make([]byte, codeLen-0x12)
r.Read(tmp)
code, _ := util.Decode(tmp, "UTF-16LE")
ReadUint16(r) // 两个空字节
tmp = make([]byte, length-codeLen-2)
r.Read(tmp)
word, _ := util.Decode(tmp, "UTF-16LE")
fmt.Println(code, word)
ret = append(ret, Entry{word, code, order})
}
return ret
}
生成
只需注意文件总长先用空字节代替,最后才写入。
代码实现:
func (MsUDP) Gen(table Table) []byte {
var buf bytes.Buffer
stamp := util.GetUint32(int(time.Now().Unix()))
buf.Write([]byte{0x6D, 0x73, 0x63, 0x68, 0x78, 0x75, 0x64, 0x70,
0x02, 0x00, 0x60, 0x00, 0x01, 0x00, 0x00, 0x00})
buf.Write(util.GetUint32(0x40))
buf.Write(util.GetUint32(0x40 + 4*len(table)))
buf.Write(make([]byte, 4)) // 待定 文件总长
buf.Write(util.GetUint32(len(table)))
buf.Write(stamp)
buf.Write(make([]byte, 28))
buf.Write(make([]byte, 4))
words := make([][]byte, 0, len(table))
codes := make([][]byte, 0, len(table))
sum := 0
for i := range table {
word, _ := util.Encode([]byte(table[i].Word), "UTF-16LE")
code, _ := util.Encode([]byte(table[i].Code), "UTF-16LE")
words = append(words, word)
codes = append(codes, code)
if i != len(table)-1 {
sum += len(word) + len(code) + 20
buf.Write(util.GetUint32(sum))
}
}
for i := range table {
buf.Write([]byte{0x10, 0x00, 0x10, 0x00})
// fmt.Println(words[i], len(words[i]), codes[i], len(codes[i]))
buf.Write(util.GetUint16(len(codes[i]) + 18))
buf.WriteByte(table[i].Order)
buf.WriteByte(0x06)
buf.Write(make([]byte, 4))
buf.Write(stamp)
buf.Write(codes[i])
buf.Write([]byte{0, 0})
buf.Write(words[i])
buf.Write([]byte{0, 0})
}
b := buf.Bytes()
copy(b[0x18:0x1c], util.GetUint32(len(b)))
return b
}
输入法词库解析(七)微软用户自定义短语.dat的更多相关文章
- 输入法词库解析(六)QQ 拼音分类词库.qpyd
详细代码:https://github.com/cxcn/dtool 前言 .qpyd 是 QQ 拼音输入法 6.0 以下版本所用的词库格式,可以在 http://cdict.qq.pinyin.cn ...
- 输入法词库解析(三)紫光拼音词库.uwl
详细代码:https://github.com/cxcn/dtool 前言 .uwl 是紫光拼音输入法(现在叫华宇拼音输入法)使用的词库. 解析 紫光的词库有点复杂,拼音用的索引,但是拼音表没有写在词 ...
- 输入法词库解析(二)搜狗拼音细胞词库.scel(.qcel)
详细代码:https://github.com/cxcn/dtool 前言 .scel 是搜狗拼音输入法所使用的细胞词库格式,可以在 https://pinyin.sogou.com/dict/ 下载 ...
- 输入法词库解析(一)百度自定义方案.def
详细代码:https://github.com/cxcn/dtool 前言 .def 是百度手机输入法-更多设置-自定义输入方案所使用的格式. 解析 码表偏移量 0x6D # 占用字节数 描述 a 1 ...
- 输入法词库解析(五)极点码表.mb
详细代码:https://github.com/cxcn/dtool 前言 mb 是极点五笔的码表格式. 解析 偏移量 描述 0x00 版本信息 0x1B 码表介绍 0x11F 所用到的按键数 0x1 ...
- 输入法词库解析(四)百度分类词库.bdict(.bcd)
前言 .bdict 是百度的分类词库格式,可以在 https://shurufa.baidu.com/dict 下载. 手机百度的分类词库格式 .bcd 是一样的,可以在 https://mime.b ...
- 用C语言将搜狗输入法词库转换成QQ拼音输入法词库
搜狗输入法词库格式: 'ni'kan'xia 你看下 'ni'kan'xia'gai'hou 你看下改后 'ni'kan'xing'ma 你看行吗 'ni'kan'zen'me'yang 你看怎么样 ...
- paip 自定义输入法多多输入法词库的备份导出以及导入
paip 自定义输入法词库的备份导出以及导入 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/ ...
- 深蓝词库转换2.2发布,支持手心输入法和Win10微软拼音
距离上一次大版本的发布已经很久很久了,中间是不是会收到一些用户的来信,提出新的需求,于是只是做小版本的更新,终于积累了一些更新后,打算做个大版本的发布了. 深蓝词库转换是一个输入法的词库互转和生成软件 ...
随机推荐
- 比我的脸还干的gan货——Python Flask Web 框架入门
Flask是一个轻量级的基于Python的web框架. 本文适合有一定HTML.Python.网络基础的同学阅读. 1. 简介 这份文档中的代码使用 Python 3 运行.是的,所以读者需要自己在电 ...
- Java模拟西宝高速公路
@ 目录 写在前面 一.仿真模拟的具体要求 二.类的设计 2.1 抽象父类PubVehicles 2.2 Expressway类 2.3 Passenger类 2.4 Timer类 2.5 Displ ...
- 利用IDEA搭建SpringBoot项目,整合mybatis
一.配置文件.启动项目 生成之后这几个文件可以删掉的 配置application spring.datasource.url=jdbc:mysql://localhost:3306/test?serv ...
- 校验日期格式为yyyy-MM-dd
/** * 校验时间 * * @param text * @return */ public static boolean checkTime(String text) { DateFormat fo ...
- Linux 更改家目录下的目录为英文
export LANG=en_US xdg-user-dirs-gtk-update
- 基于 Hexo 从零开始搭建个人博客(二)
阅读本篇前,请先配置好相应的环境,请仔细阅读教程 基于 Hexo 从零开始搭建个人博客(一). 原文链接:基于 Hexo 从零开始搭建个人博客(二) 前言 博客搭建过程遇到任何问题,优先在本页面搜索, ...
- 【设计过程】.NET ORM FreeSql WhereDynamicFilter 动态表格查询功能
前言 最近几乎每天40度,越热越不想面对电脑,还好开源项目都比较稳定没那么多待解决问题,趁着暑假带着女儿学习游泳已略有小成.游泳好处太多了,建议有孩子的都去学学,我是在岸边指导大约一周左右就学会了,目 ...
- Nginx配置解决NetCore的跨域
使用Nginx配置解决NetCore的跨域 废话不多说,直接上Nginx配置 server { listen 80; server_name 你的Id或域名; location / { add_hea ...
- ROS机械臂 Movelt 学习笔记3 | kinect360相机(v1)相关配置
目标是做一个机械臂视觉抓取的demo,在基地里翻箱倒柜,没有找到学长所说的 d435,倒是找到了一个老古董 kinect 360. 前几天就已经在旧电脑上配置好了,现在记录在新电脑上的配置过程. 1. ...
- 2022-7-21 第七组 pan小堂 继承与super与this
1.继承 1.1继承的概述 在现实生活中,继承一般指的是子女继承父辈的财产.在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系. 1.2继承的格式 class 子类 ...