問(wèn)題
最近使用protobuf(google出品的一種序列化協(xié)議)存儲(chǔ)中文時(shí),看到一種類似\346\200\241\346\200\241\346\200的編碼,試用各種常用的編碼格式用編碼轉(zhuǎn)換工具都不可以,在java,python中卻可以在不明確指定編碼方式的情況下識(shí)別成功,現(xiàn)在需要在web頁(yè)解碼方便直接查看,js默認(rèn)的解編碼函數(shù)搞不定。所以查查看
八進(jìn)制編碼
其實(shí)他還是utf8編碼,不過(guò)通常的utf8編碼使用16進(jìn)制表示,這種編碼不常見(jiàn)的使用了8進(jìn)制表示。其實(shí)將這里的8進(jìn)制轉(zhuǎn)為16進(jìn)制,和utf8的編碼是完全一致的,也就是說(shuō)在內(nèi)存中的字節(jié)是一致的,所以可以被java,python直接識(shí)別,但是按8進(jìn)制方式顯示,就顯得很特別了。
# 在python中可以直接用decode("utf-8")解:
>>> print("\344\275\240\345\245\275".decode("utf-8"))
你好
utf8的多種形式
"你好"的各個(gè)平臺(tái)編碼,他們之間的區(qū)別就是編碼的二進(jìn)制的不同的可讀方式,八進(jìn)制確實(shí)用的少。
| 平臺(tái) | 舉例 | 備注 |
|---|---|---|
| 在線轉(zhuǎn)碼平臺(tái) | 你好 |
就是把unicode的 \u 前綴轉(zhuǎn)為了 &#x |
| python | \xe4\xb8\xad\xe6\x96\x87 |
就是utf8 每個(gè)字節(jié)16進(jìn)制的前面加上 \x |
| url | %E4%BD%A0%E5%A5%BD |
utf8 每個(gè)字節(jié)16進(jìn)制的前面加上 % |
| protoBuf | \344\275\240\345\245\275 |
utf8 每個(gè)字節(jié)8進(jìn)制的前面加上 \ |
js實(shí)現(xiàn) 八進(jìn)制utf8的解碼
沒(méi)有成品,就自己造。思路就是正則匹配字符串,三位三位拿,轉(zhuǎn)為16進(jìn)制,加%轉(zhuǎn)為url的編碼方式,然后使用js的解碼函數(shù)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函數(shù)產(chǎn)生的空字符串
encoded += "%" + parseInt(token, 8).toString(16)
}
})
return decodeURIComponent(encoded);
});
return decoded
}
總結(jié)
至此問(wèn)題解決了。代碼離不開(kāi)編碼的處理,常用有很多種編碼方式,編碼的核心作用就是把文字映射到二進(jìn)制,方便機(jī)器理解計(jì)算。在讀寫(xiě)文件,web傳輸時(shí)常常需要指定編碼方式,但我們也不需要關(guān)注編碼的"長(zhǎng)相",因此碰見(jiàn)一個(gè)不常見(jiàn)的“長(zhǎng)相”,還以為是不常用或者經(jīng)過(guò)了壓縮的編碼。