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

前言

微软拼音和微软五笔通用的用户自定义短语 dat 格式。

解析

前 8 个字节标识文件格式 machxudp,微软五笔的 lex 格式是 imscwubi

下面 8 个字节应该是版本号。

接下来每 4 字节一组,分别表示偏移表开始词条开始文件总长词条数导出的时间戳

然后补 0 一直到偏移表开始

偏移表记录了每个词条从词条开始的偏移量,每 4 个字节一组。

接下来就是词条本体部分:

# 占用字节数 描述
4 10 00 10 00 标记
a 2 该词条总字节长 - 词占用的字节长
1 在候选中的位置
1 0x060x13,未知
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的更多相关文章

  1. 输入法词库解析(六)QQ 拼音分类词库.qpyd

    详细代码:https://github.com/cxcn/dtool 前言 .qpyd 是 QQ 拼音输入法 6.0 以下版本所用的词库格式,可以在 http://cdict.qq.pinyin.cn ...

  2. 输入法词库解析(三)紫光拼音词库.uwl

    详细代码:https://github.com/cxcn/dtool 前言 .uwl 是紫光拼音输入法(现在叫华宇拼音输入法)使用的词库. 解析 紫光的词库有点复杂,拼音用的索引,但是拼音表没有写在词 ...

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

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

  4. 输入法词库解析(一)百度自定义方案.def

    详细代码:https://github.com/cxcn/dtool 前言 .def 是百度手机输入法-更多设置-自定义输入方案所使用的格式. 解析 码表偏移量 0x6D # 占用字节数 描述 a 1 ...

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

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

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

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

  7. 用C语言将搜狗输入法词库转换成QQ拼音输入法词库

    搜狗输入法词库格式: 'ni'kan'xia 你看下 'ni'kan'xia'gai'hou 你看下改后 'ni'kan'xing'ma 你看行吗 'ni'kan'zen'me'yang 你看怎么样 ...

  8. paip 自定义输入法多多输入法词库的备份导出以及导入

    paip 自定义输入法词库的备份导出以及导入 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/ ...

  9. 深蓝词库转换2.2发布,支持手心输入法和Win10微软拼音

    距离上一次大版本的发布已经很久很久了,中间是不是会收到一些用户的来信,提出新的需求,于是只是做小版本的更新,终于积累了一些更新后,打算做个大版本的发布了. 深蓝词库转换是一个输入法的词库互转和生成软件 ...

随机推荐

  1. Bash脚本debug攻略

    初学Bash时, 我从未想过想过bash也能debug, 也从未想过去debug Bash脚本. 随着技术的增长, 写的脚本越来越复杂, 使用echo打印日志来调试脚本的方式越来越捉襟见肘了. 直到某 ...

  2. NOI-Online一日游(小炒肉心态爆炸记)

    提高组 早上起来赶来机房,逃掉数竟,耶!(光凯:?? T1 It takes me a long time想T1 努力了一个小时的成果 成功码出暴力代码,时间复杂度\(O(n^2)\) 㵘到15分 刑 ...

  3. react 吸顶实现

    今天获取到一个需求,其实就是吸顶的需求,页面下滑,某一块dom隐藏时发生吸顶现象.这种特效其实老生常谈了,但是在这次做的时候,突发奇想,能否将其做成一个 hook ,从而实现出传递ref即可使得 do ...

  4. SpringBoot整合RabbitMQ实现六种工作模式

    RabbitMQ主要有六种种工作模式,本文整合SpringBoot分别介绍工作模式的实现. 前提概念 生产者 消息生产者或者发送者,使用P表示: 队列 消息从生产端发送到消费端,一定要通过队列转发,使 ...

  5. 别无分号只此一家,Python3接入支付宝身份认证接口( alipay.user.certify)体系(2021年最新攻略)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_184 目前国内身份认证体系做的比较不错的大抵就是支付宝和微信两家了,支付宝的身份验证基于支付宝app的实人认证能力,采用多因子认证 ...

  6. Vue 自定义事件 && 组件通信

    1 App.vue 2 <template> 3 <!-- 4 组件的自定义事件: 5 1.一种组件间通信的方式,使用于:子组件===>父组件 6 2.使用场景:A是父组件,B ...

  7. benchmark性能测试

    目录 benchmark介绍 benchmark运行 benchmark运行参数 benchmark性能测试案例 benchmark介绍 基准测试主要是通过测试CPU和内存的效率问题,来评估被测试代码 ...

  8. CF208E Blood Cousins(DSU,倍增)

    倍增求出祖先,\(\text{DSU}\)统计 本来想用树剖求\(K\)祖,来条链复杂度就假了 #include <cstring> #include <cstdio> #in ...

  9. 209. 长度最小的子数组--LeetCode

    来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/minimum-size-subarray-sum 著作权归领扣网络所有.商业转载请联系官方授权,非商业 ...

  10. Aoac唤醒的软件方案

    Aoac唤醒 这篇文章包含了Win10下的Aoac唤醒和Win11下的Aoac唤醒的不同地方,在结尾处: 从Win10时代开始,通过软件来唤醒机器是一个很常见的事情了,但是很少有文档去将如何通过AOA ...