1. 程式人生 > >【原創】通俗易懂地解決中文亂碼問題(1) --- 跨平臺亂碼

【原創】通俗易懂地解決中文亂碼問題(1) --- 跨平臺亂碼

本來是隻打算寫一篇關於中文亂碼的blog的,但是發現要講的東西跨度有點大,不好寫到同一篇裡面,所以分開了。

這一篇重點在編碼的理論,另一篇重點在解決問題及思路。

一、問題的開始

中文亂碼問題經常出現在實際工程中,尤其容易發生在經驗不足的團隊對問題預估不足的情況下。網站開發,社交聊天等對輸入資訊不可控的應用往往是重災區。再加上移動網際網路的火熱,新興字元和表情也開始頻繁被使用,如果不能達到足夠的支援,對使用者體驗來說是個災難。所以,在設計系統的開始,要嚴格把控字元編碼。以大體明確怎麼做是不會出錯的(嚴格按規則限制往往難以把控,並且容易漏掉被鑽空子,所以做到不出錯是出發點)。

二、Unicode

Unicode是本文的重點。

Unicode是一種通用字符集,是對字元的定義。和之對應的也有,比如 ISO 8859-1。但Unicode被廣泛使用併成為業界的標準,所以我們可以認為Unicode就是對計算機裡字元的定義,在記憶體中的表現是0,1串。

而且,Unicode的編碼很乾淨,它為 字元而非字形定義唯一的程式碼。換句話說,統一碼以一種抽象的方式(即數字)來處理字元,並將視覺上的演繹工作(例如字型大小、外觀形狀、字型形態、文體等)留給其他軟體來處理,例如網頁瀏覽器或是文書處理器。舉個例子,如 “ɑ/a”、“強/強”、“戶/戶/戸”。(引自wiki)

這樣,Unicode本身要做的任務很明確,就是合適的擴充編碼。

三、UTF-8

UTF-8是Unicode的一種實現方式,是可變長的字元編碼。與之對應的還有GBK(固定長度),Latin,UTF-16(Unicode的完全式)等等。

這些為什麼是實現方式呢?不是Unicode已經定義好了嗎?其實這也是計算機學科經常用的方法,這些不同的編碼就類似於針對Unicode的各種trick。

舉個簡單的例子,一個整形陣列A[],那麼給A[]排序這個定義就相當於Unicode。那麼是採用快排、堆排還是歸併,用正序還是倒序排列結果,這些方法就相當於編碼格式這些都是對這個定義的具體實現過程,但是方法不同。

因此,不論是UTF-8、GBK、Latin等,其還原的編碼結果都是同一個Unicode

編碼。

四、Unicode和UTF-8的關係及轉換過程

那麼對於Unicode和UTF-8的關係,可以用上面的例子理解。不過真實情況應該是類似下面這樣的。

比如"國"字的Unicode編碼定義為 00000000 00000000 00110100 11000000 (假設)。

由於其低16位都是0,為了減少儲存和傳輸這個字在位元組上的浪費,就選擇高16位來表示。同時由於UTF-8是可變長的,所以需要標識位來標識這個編碼到底使用了幾個位元組。

所以 “國”字 對應的 UTF-8的編碼應該是 11100011 10010011 10000000(加粗的是原編碼的高16位)。

轉換公式:1110xxxx(E0-EF) 10yyyyyy 10zzzzzz,顯示標明的是標誌位)。

以下附上UTF-8的編碼方式:(引自wiki)

五、中文跨平臺亂碼及解決辦法

有了以上知識的積累,我們可以分析為什麼跨平臺會出現亂碼?明明好好的Unicode怎麼就亂了呢?

那麼很直觀我們會想到應該是編碼格式不相容

對於windows平臺,編碼格式是GBK,對應的漢字是兩個位元組長度。對於Linux平臺,編碼格式是UTF-8,對應的漢字是3個位元組。(這裡都是預設情況)

那麼我們還用上面 排序這個例子來解釋。

比如現在Unicode用 {1,2,3}定義,GBK代表正序排列,UTF-8代表倒序排列。那麼現在Unicode在GBK下的編碼是{1,2,3},在UTF-8下的編碼是{3,2,1}。

現在由GBK編碼還原Unicode編碼,那麼正向解析GBK就是Unicode。而由UTF-8編碼還原Unicode編碼,需要逆向解析UTF-8編碼。這都是和自身對應的。

但是如果一個把GBK編碼誤認為是UTF-8,那麼逆向解析後的結果是{3,2,1}。首先這個結果不是原始的Unicode編碼,那麼其轉換的結果不是我們需要的。其次,很可能這個編碼結果在Unicode中還沒有定義,可能會出現類似空格一樣的空白符。

因此這就是跨平臺中文亂碼的原因,編碼和解碼方式出現了差別。

解決辦法:

解決辦法其實有很多種,根據自身應用的不同既可以選擇在程式碼端進行編碼的轉換(比如java的 String str = new String(str.getBytes("GBK"), "UTF-8");),也可以在輸入端進行編碼格式的調整。

不過歸結下來只有一點,即 如果當前輸入是GBK編碼,而你需要的又是UTF-8編碼,那麼:

1. 用GBK的解碼方式轉換成Unicode。

2. 使用UTF-8編碼進行編碼。

六、中文編碼一些有趣的應用

這裡我只想到了war3(感謝@殭屍的提醒)上面一些搞笑的名字(一不小心貌似暴露了什麼。。),後面想到其它還會更新的。

比如下面這個圖:

藍圈裡面的玩家名字是正常顯示的,為綠色。紅圈裡面的是藍色,相當於突破了war3的限制顯示了其它特殊顏色。

這個做法就是對應名字後面加上|r。這是一個轉義符,合理的利用了war3給使用者開放的字符集併產生了特殊效果。所以這也是我開篇說的嚴格把控字符集是很難的,控制到不出錯(比如系統亂碼)已經挺好了。

轉載請註明出處,謝謝~  http://www.cnblogs.com/xiaoboCSer/p/4175361.html

相關推薦

原創通俗易懂解決中文亂碼問題1 --- 跨平臺亂碼

本來是隻打算寫一篇關於中文亂碼的blog的,但是發現要講的東西跨度有點大,不好寫到同一篇裡面,所以分開了。 這一篇重點在編碼的理論,另一篇重點在解決問題及思路。 一、問題的開始 中文亂碼問題經常出現在實際工程中,尤其容易發生在經驗不足的團隊對問題預估不足的情況下。網站開發,社交聊天等對輸入資訊不

原創通俗易懂解決中文亂碼問題2 --- 分析解決Mysql插入移動端表情符報錯 ‘incorrect string value: '\xF0...

當然,如果只是針對解決這個Mysql插入報錯問題,本篇足夠了。 一、定位錯誤 定位錯誤絕對是至關重要的一環。我建議遇到問題耐心分析一下比較好,畢竟“不是所有的牛奶都叫特侖蘇”。 引起同一個問題的可能有很多,別人的解決方案也許並不適合自己。 那先看看問題出現在哪了,報錯如下: 發現的確

原創智慧合約安全事故回顧分析1:The Dao事件

首先需要說明的一點是,這個世界上沒有絕對安全的技術。在區塊鏈發展的十年裡,各種基於區塊鏈的數字貨幣引發的安全事故層出不窮,這些安全威脅主要來源有三個方面: 自身安全機制的問題,類似智慧合約。 生態安全問題,交易所,礦池,網站等等。 使用者安全問題,包括個人賬號密碼的洩露,被釣魚等。

原創python3將圖片寫入mysql資料庫

01.環境準備使用的包:pymysqlpymysql下載地址:https://pypi.python.org/pypi/PyMySQL#downloads02.pymysql安裝:03.mysql的blob欄位解釋:BLOB型別的欄位用於儲存二進位制資料MySQL中,BLOB

演算法B+樹的研讀及實現1

【前言】 為什麼要明白b+樹?假如大家有操作資料庫及開發有關資料庫的經驗,那麼肯定知道索引這個概念,那麼進一步問你什麼叫索引? mysql的索引就是B+樹,而其他資料庫我不太清楚,但是,b+樹是一般的索引演算法,當然,oracle、postgres等資料庫聽說也支援r樹的索

爬蟲手把手教你寫網路爬蟲1

介紹 什麼是爬蟲? 先看看百度百科的定義: 簡單的說網路爬蟲(Web crawler)也叫做網路鏟(Web scraper)、網路蜘蛛(Web spider),其行為一般是先“爬”到對應的網頁上,再把需要的資訊“鏟”下來。 為什麼學習爬蟲? 看到這裡,有人就要問了:Google、百度等

原創mysql 正則匹配中文&…

含中文: where name regexp  '[^ -~]' 不含中文:  where name not regexp '^[^ -~]' 後來說需要查詢日文 參考資料得知: utf-8 (unicode) /u4e00-/u9fa5 (中文) /x3130-/x318f (韓文) /xac00

原創新韭菜日記2---人性的缺點1:為什麼總是急著賣漲的,而捨不得割肉?

心理學書上寫的 為什麼總是急著賣漲的,而捨不得割肉? 前提情景:手上已經持股 行為模式:手上持有的股票,漲價後非常想賣                   手上持有的股票,跌價後不想割肉 心

原創給定隨機數的取值範圍最小值、最大值,且要求多次取得的隨機數最後的結果有一個固定的平均值

給定隨機數的取值範圍(最小值、最大值),且要求多次取得的隨機數最後的結果有一個固定的平均值。 演算法如下: /****** * author ztg 281099678 2018-12-06 * @param $min float 範圍最小值 * @param $max

原創linux spinlock/rwlock/seqlock原理剖析基於ARM64

# 背景 - `Read the fucking source code!` --By 魯迅 - `A picture is worth a thousand words.` --By 高爾基 說明: 1. Kernel版本:4.14 2. ARM64處理器,Contex-A53,雙核 3. 使用工具:S

原創CentOS 7搭建多例項MySQL8想要幾個搞幾個

起因    最近專案上開始重構,可能會用到主從加讀寫分離的情況,就想先在本地搭一個出來試試效果,結果百度一搜出來一大堆,然而自己去踩坑的沒幾個,絕大多數都是去抄的別人的內容,關鍵是實際應用中還會出錯,瀏覽器開了接近二十個標籤頁,試了好幾個都有問題,完全用不了,時間浪費了不說,還會讓你很憋屈

原創xenomai與VxWorks實時性對比資源搶佔上下文切換對比

版權宣告:本文為本文為博主原創文章,轉載請註明出處。如有問題,歡迎指正。部落格地址:https://www.cnblogs.com/wsg1100/ 可能大部分人一直好奇VxWorks與xenomai對比,實時性孰優孰劣,正好筆者最近要做一個這方面的對比。**宣告:下面資料,僅供個人參考,有不對的地方還請指

ShiroApache Shiro架構之身份認證Authentication

trac pretty asm 安全保障 軟件測試 釋放 model tac 讀取配置文件 Shiro系列文章: 【Shiro】Apache Shiro架構之權限認證(Authorization) 【Shiro】Apache Shiro架構之集成web

整理軟件工程復習提綱維護

評價 描述 nbsp 參考 操作 text 吸引 復習 組織 章魚小年糕整理,如果有錯誤歡迎提出,若要二次修改發布,請留言,謝謝^_^! 概念 軟件維護:軟件在已經交付使用之後,為了改正錯誤或滿足新的需求修改軟件的過程。 文檔:有關計算機程序功能、設計、編制、使用的文字或圖

fetch跨域請求附帶cookiecredentials

allow src ssi ann oct o-c ech .com 頭部 HTTP訪問控制 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS 解決跨域的方式有很多種,本文介紹“跨域請

充分利用你的Azure將Azure用作雲計算平臺1

遠程 spa http pac 雲計算 學習 .com xshel 利用 本文將圍繞幾個步驟來講。 因為本人是MSP,微軟送了150刀的額度給我隨便使用。這篇文章是要講將Azure用作雲計算平臺,對於我來說,我是做機器學習的,那麽Azure就要有機器學習的平臺。 本文的目的

gulp前端自動化工具---gulp的使用------凡塵

app 一起 dex 前端自動化 指定 sass css 文件的 等待 什麽是gulp? 基於node的自動化構建工具 擴展:開發的時候分為2個節點一個是開發階段 另一個是部署階段 開發階段:源文件不會被壓縮

AI基礎python:openCV——處理鼠標事件1

python:opencv 處理鼠標 一、用戶通過鼠標對圖像視窗最常見的操作有: 左鍵單擊按下 左鍵單擊擡起 左鍵按下拖動 鼠標指針位置移動 二、單次單擊操作響應事件及順序 Opencv中setMouseCallback()創建了一個鼠標回調函數,每次在圖像上單擊鼠標左鍵再擡起的過程,

201803122018年03月12日隨想

post 而是 有一個 然而 clas OS you pos 一個 今天有一個熱點事件,在幾個群裏都有提及。 我以為是假的。沒想到是真的。果然還是太young了。 總結: 有的事,你認為是假的,它是真的。比如今天的焦點事件。 有的事,你認為一定是假的,偏偏是真

PAT1135Is It A Red-Black Tree30

earch represent uno nbsp pac ber key strong 節點 There is a kind of balanced binary search tree named red-black tree in the data structure.