参考深蓝词库转换
百度 pc 分类词库.bdict 和手机.bcd 是一样的
码表偏移 0x350
词库不带拼音表,需要根据词库规纳出来,参考深蓝
内部根据是否含有英文分为几种格式
格式一
纯中文
占用字节数 | 描述 |
---|---|
4 | 拼音长,词长 |
由上一项决定 | 拼音,(声母索引<24+韵母索引<33) |
由上一项决定 | 词,utf-16le 编码 |
带英文的,结构差不多,声母索引为 0xFF 表示英文字母
格式二:纯英文
编码使用 ascii
占用字节数 | 描述 |
---|---|
4 | 词长 |
由上一项决定 | 词,ascii 编码 |
格式三:编码和词不等长
拼音不再使用索引,而是直接使用 utf-16le 编码
占用字节数 | 描述 |
---|---|
4 | 编码字节长 |
2 | 2 个空字节 |
2 | 词长 |
由编码字节长决定 | 编码,utf-16le |
由词长决定 | 词,utf-16le 编码 |
代码
golang
var bdictSm = []string{
"c", "d", "b", "f", "g", "h", "ch", "j", "k", "l", "m", "n",
"", "p", "q", "r", "s", "t", "sh", "zh", "w", "x", "y", "z",
}
var bdictYm = []string{
"uang", "iang", "iong", "ang", "eng", "ian", "iao", "ing", "ong",
"uai", "uan", "ai", "an", "ao", "ei", "en", "er", "ua", "ie", "in", "iu",
"ou", "ia", "ue", "ui", "un", "uo", "a", "e", "i", "o", "u", "v",
}
func ParseBaiduBdict(rd io.Reader) []Pinyin {
ret := make([]Pinyin, 0, 1e5)
data, _ := ioutil.ReadAll(rd)
r := bytes.NewReader(data)
// utf-16le 转换器
decoder := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder()
r.Seek(0x350, 0)
for r.Len() > 4 {
// 拼音长,也是词长
codeLen, _ := r.ReadByte()
r.Seek(3, 1) // 丢掉跟着的3个0
// 判断下两个字节
tmp := make([]byte, 2)
r.Read(tmp)
if tmp[0] == 0 && tmp[1] == 0 {
r.Read(tmp)
wordLen := bytesToInt(tmp)
codeSli := make([]byte, codeLen*2)
r.Read(codeSli)
wordSli := make([]byte, wordLen*2)
r.Read(wordSli)
codeSli, _ = decoder.Bytes(codeSli)
wordSli, _ = decoder.Bytes(wordSli)
ret = append(ret, Pinyin{string(wordSli), []string{string(codeSli)}, 1})
continue
}
// 全英文的词,编码和词是一样的
if int(tmp[0]) >= len(bdictSm) && tmp[0] != 0xff {
r.Seek(-2, 1)
eng := make([]byte, codeLen)
r.Read(eng)
ret = append(ret, Pinyin{string(eng), []string{string(eng)}, 1})
continue
}
r.Seek(-2, 1)
// 一般格式
code := make([]string, 0, codeLen)
for i := 0; i < int(codeLen); i++ {
smIdx, _ := r.ReadByte()
ymIdx, _ := r.ReadByte()
// 带英文的词组
if smIdx == 0xff {
code = append(code, string(ymIdx))
continue
}
code = append(code, bdictSm[smIdx]+bdictYm[ymIdx])
}
// 读词
wordSli := make([]byte, 2*codeLen)
r.Read(wordSli)
wordSli, _ = decoder.Bytes(wordSli)
ret = append(ret, Pinyin{string(wordSli), code, 1})
}
return ret
}