详细代码: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. Django WEB开发 - Django 3.0 Tutorial入门

    1. Django 官方网站 https://docs.djangoproject.com/zh-hans/3.0/intro/tutorial01/ 2. Model View Controller ...

  2. centos7 nginx 域名能ping通,但无法打开网页

    方法一:关闭防火墙 sudo systemctl stop firewalld.service 方法二:容许80端口访问 vim打开iptables, 命令如下: #vim /etc/sysconfi ...

  3. 如何用 身份证OCR 接口进行快速开发

    最近公司项目有一个身份证文字识别的小需求,想着如果用现成的API就可以大大提高开发效率,在网上的API商店搜索了一番,发现了 APISpace,它里面的身份证OCR非常符合我的开发需求.   身份证O ...

  4. Webpack干货系列 | Webpack5 怎么处理字体图标、图片资源

    程序员优雅哥(youyacoder)简介:十年程序员,呆过央企外企私企,做过前端后端架构.分享vue.Java等前后端技术和架构. 本文摘要:主要讲解在不需要引入额外的loader的条件下运用Webp ...

  5. postgres备份与恢复

    一  利用pgAdmin工具进行备份与恢复 pgAdmin是postgres官方的客户端管理工具,可以进行数据库的涉及与维护. 示例:以logs库为例记录操作       1)  右击需要备份的数据( ...

  6. 我也是醉了,Eureka 延迟注册还有这个坑!

    Eureka 有个延迟注册的功能,也就是在服务启动成功之后不立刻注册到 Eureka Server,而是延迟一段时间再去注册,这样做的主要目的是因为虽然服务启动成功了,可能还有一些框架或者业务的代码没 ...

  7. Vue3系列1--配置环境和创建项目

    1.安装nodejs(建议最新版本) 下载地址:下载 | Node.js 中文网 在安装的过程中建议不要装在C盘,安装完成配置环境变量,并且建议讲缓存路径更改. 安装完成后通过查看nodejs版本和n ...

  8. Axure RP 8 实现 圆角文本框 圆角带筛选的下拉列表框 可自动显示滚动条

    刚开始用Axure 会发现 Axure 元件库并不是很齐全,很多元件需要自己想办法解决 或者去网上去找.其实个人建议网上有现成的元件可以就下载就不必花时间去折腾.除非你也想练练手,原型这种东西除非高保 ...

  9. Veux mapState、mapGetters、mapActions、mapMutations && Vuex命名空间

    1 # 一.四个map方法的使用 2 # 1.mapState方法:用于帮助我们映射state中的数据为计算属性 3 computed:{ 4 // sum(){ 5 // return this.$ ...

  10. HttpClient 在vivo内销浏览器的高并发实践优化

    作者:vivo 互联网服务器团队- Zhi Guangquan HttpClient作为Java程序员最常用的Http工具,其对Http连接的管理能简化开发,并且提升连接重用效率:在正常情况下,Htt ...