问题
最近使用protobuf(google出品的一种序列化协议)存储中文时,看到一种类似\346\200\241\346\200\241\346\200
的编码,试用各种常用的编码格式用编码转换工具都不可以,在java,python中却可以在不明确指定编码方式的情况下识别成功,现在需要在web页解码方便直接查看,js默认的解编码函数搞不定。所以查查看
八进制编码
其实他还是utf8编码,不过通常的utf8编码使用16进制表示,这种编码不常见的使用了8进制表示。其实将这里的8进制转为16进制,和utf8的编码是完全一致的,也就是说在内存中的字节是一致的,所以可以被java,python直接识别,但是按8进制方式显示,就显得很特别了。
# 在python中可以直接用decode("utf-8")解:
>>> print("\344\275\240\345\245\275".decode("utf-8"))
你好
utf8的多种形式
"你好"的各个平台编码,他们之间的区别就是编码的二进制的不同的可读方式,八进制确实用的少。
平台 | 举例 | 备注 |
---|---|---|
在线转码平台 | 你好 |
就是把unicode的 \u 前缀转为了 &#x |
python | \xe4\xb8\xad\xe6\x96\x87 |
就是utf8 每个字节16进制的前面加上 \x |
url | %E4%BD%A0%E5%A5%BD |
utf8 每个字节16进制的前面加上 % |
protoBuf | \344\275\240\345\245\275 |
utf8 每个字节8进制的前面加上 \ |
js实现 八进制utf8的解码
没有成品,就自己造。思路就是正则匹配字符串,三位三位拿,转为16进制,加%
转为url的编码方式,然后使用js的解码函数decodeURIComponent() 解码最终得到中文。
function decodeOctUtf8(octStr){
decoded = octStr.replace(/(\\\d\d\d){3,}/g, function(word){
tokens = word.split("\\")
encoded = ''
tokens.forEach(function(token, idx){
if(token.length > 0){ // 去掉split函数产生的空字符串
encoded += "%" + parseInt(token, 8).toString(16)
}
})
return decodeURIComponent(encoded);
});
return decoded
}
总结
至此问题解决了。代码离不开编码的处理,常用有很多种编码方式,编码的核心作用就是把文字映射到二进制,方便机器理解计算。在读写文件,web传输时常常需要指定编码方式,但我们也不需要关注编码的"长相",因此碰见一个不常见的“长相”,还以为是不常用或者经过了压缩的编码。