浅入GBK编码

GBK编码范围

浅入GBK编码_第1张图片
之前GBK编码说不熟悉吧,也知道一二,要说熟悉,自动动手把某个汉字的GBK编码打印出来,那是万万不能的,总觉得这个很高深,要用的时候去网上复制粘贴就行了,不用深究。

暴力穷举

这次在写Javascript时,要用到把汉字字符串转GBK编码,因为没有现成的函数,在网上搜索到别人的暴力穷举方法,顺带就把GBK的转换原理也了解一下。
Javascript里GBK编码转汉字字符串是如下方法:
const gbkBuf = new Uint8Array([196, 227, 186, 195, 49, 50, 51])
new TextDecoder(‘gbk’).decode(gbkBuf) // “你好123”

通过这种方法,我们可以遍历所有GBK编码,直接列出所有汉字

const ranges = [
[0xA1, 0xA9, 0xA1, 0xFE],
[0xB0, 0xF7, 0xA1, 0xFE],
[0x81, 0xA0, 0x40, 0xFE],
[0xAA, 0xFE, 0x40, 0xA0],
[0xA8, 0xA9, 0x40, 0xA0],
[0xAA, 0xAF, 0xA1, 0xFE],
[0xF8, 0xFE, 0xA1, 0xFE],
[0xA1, 0xA7, 0x40, 0xA0],
]
const codes = new Uint16Array(23940)
let i = 0

for (const [b1Begin, b1End, b2Begin, b2End] of ranges) {
for (let b2 = b2Begin; b2 <= b2End; b2++) {
if (b2 !== 0x7F) {
for (let b1 = b1Begin; b1 <= b1End; b1++) {
codes[i++] = b2 << 8 | b1
}
}
}
}
const str = new TextDecoder(‘gbk’).decode(codes)

// 编码表
const table = new Uint16Array(65536)
for (let i = 0; i < str.length; i++) {
table[str.charCodeAt(i)] = codes[i]
}

这样就构建出了,以汉字为key,以两个字节GBK编码为value的GBK映射表table

直接查表

function stringToGbk(str) {
const buf = new Uint8Array(str.length * 2)
let n = 0

for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i)
if (code < 0x80) {
buf[n++] = code
} else {
const gbk = table[code]
buf[n++] = gbk & 0xFF
buf[n++] = gbk >> 8
}
}
return buf.subarray(0, n)
}

stringToGbk(‘你好123’) // [196, 227, 186, 195, 49, 50, 51]

有了全部汉字的映射表后,直接查表即可,但是这里需要考虑到汉字和ASCII字符混合的情况,所以如果碰到0x80以下的,不能转换。

之前畏难,现在发现了解了编码的码位空间,转换起来也不是很复杂的事情。

你可能感兴趣的:(c++,前端)