vim編碼規則

2021-09-12 07:36:06 字數 3857 閱讀 8422

1 字元編碼基礎知識

字元編碼是計算機技術中最基本和最重要的知識之一。如果缺乏相關知識,請自行惡補之。這裡僅做最簡要的說明。

1.1 字元編碼概述

所謂的字元編碼,就是對人類發明的每乙個文字進行數位化表示。最經典的ascii編碼就是西方人發明的針對英文本元的編碼方法,包括26個英文本母、數字、標點、特殊字元等。問題是,這種編碼的範圍是0-127,只能對128個字元進行編碼。當計算機來到其他國家後發現,除了英語,還有大量的其他語言,而且涵蓋的字元也遠遠多於128個。為此,各個國家開始針對自己的語言進行編碼工作,例如中國的gbk,日本的cjk,等等。

這雖然解決了ascii編碼不夠用的問題,但是卻帶來了另外乙個更加嚴重的問題。那就是各個國家的字元編碼不統一,導致無法進行統一處理。於是乎,著名的unicode出現了,unicode編碼範圍非常大,可以涵蓋全球所有語言的字元。

1.2 區分字符集(charset)和字元編碼(char encoding)

這兩個術語有時候不進行區分的使用,但是理解其區別對於理解字元編碼至關重要。

**點(code point) 

也就是我們前面說到的,為每乙個字元分配乙個數字序號。例如在ascii字符集中,字元a被分配成65號,那就是說a的**點是65。一種編碼規範中,所有的**點的集合就是字符集。

字元編碼 

字元編碼是**點的二進位制儲存格式。還是前面的例子,在ascii字符集中,a的**點是65。而這個65究竟是怎麼用二進位制0和1序列表示呢?這就是字元編碼的工作。在ascii編碼中,這個65被儲存為01000001,一共佔據乙個位元組(8個二進位制位)。

說到這裡也許你會覺得,這中區別也沒什麼啊,這主要是因為在我們的例子中ascii字符集的**點只有一種字元編碼方式,也就是ascii字元編碼。而這在其他字符集中卻不總是這樣,例如unicode字符集。

unicode字符集,規定了全球每乙個字元的**點,例如英文本母a在unicode字符集中的**點是65(哈哈,這個**點與ascii是相容的),然而65的存放格式卻有很多方式:例如在utf-8字元編碼規範中被儲存為8個二進位制位:01000001,而在ucs-16中被儲存為16個二進位制位:0000000001000001,而在ucs-32中被儲存為32個二進位制位:00000000000000000000000001000001。

說到這裡,就明白了,unicode字符集對應有很多不同的字元編碼方式:utf-8,ucs-16,ucs-32等等。 

而ascii字符集只有一種編碼方式:ascii字元編碼。

unicode字符集的不同編碼方式是為了適應不同的環境而被創造出來的,例如utf-8被用來網路傳輸,檔案存放,ucs-16則被用來作為記憶體中的存放方式,以利於快速統一計算。

現如今,雖然unicode字符集已經獲得廣泛採用,然而歷史遺留的其他字符集仍大量存在。 

近年來,字符集的概念很少被提及,字元編碼則更多的被使用。

1.3 字元編碼與顯示

對字元進行編碼只是完成了存放、處理和傳輸,要想把字元的形狀繪製出來,還要有對應的字型以及渲染手段。

對於gui程式,作業系統都會提供api來對指定字元進行渲染繪製。對於終端來說,終端有乙個字元編碼的屬性,從而把接收到的二進位制位元組流按照這個字元編碼進行解析,然後呼叫相應的渲染引擎來對其進行顯示,詳情請參考我的一篇博文:從呼叫printf()到顯示器上看到字串。

2 vim讀取、顯示、儲存文字檔案過程分析

2.1 vim涉及到的字元編碼

(1) 磁碟檔案的字元編碼 

存放在磁碟上的文字檔案,是按照一定的字元編碼進行儲存的,不同的檔案可能使用了不同的字元編碼。 

這在vim中被叫做:fileencoding。

(2) vim緩衝區以及介面的字元編碼 

vim執行時,其選單、標籤、以及各個緩衝區統一使用一種字元編碼方式。 

這在vim中被叫做:encoding。

(3) 終端使用的字元編碼 

終端同一時刻只能使用一種字元編碼,並按照這種編碼從接收到的位元組流中識別字元,並顯示,終端的字元編碼是可以動態調整的。 

這在vim中被叫做:termencoding。

2.2 vim讀、顯、存分析

(1)讀檔案 

vim開啟檔案時,並不知道檔案的字元編碼,所以不得不進行探測。探測是按照一定的優先順序進行測試。依據的標準就是:fileencodings。vim逐一測試fileencodings變數指定的字元編碼方式,直到找到認為合適的然後把這種字元編碼方式設定為fileencoding變數。

然後把檔案中的編碼轉換成encoding指定的編碼方式,存入檔案緩衝區中。 

(2)顯示檔案 

vim把檔案讀取完畢並以encoding編碼存放到緩衝區記憶體之後,會根據termencoding指定的終端編碼方式,轉換成termencoding編碼後,寫入到終端。此時,終端按照自身的編碼屬性識別出乙個個的字元,呼叫渲染引擎繪製到螢幕上。

(3)儲存檔案 

vim把緩衝區中的encoding編碼的位元組集合轉換成fileencoding編碼後寫入磁碟,完成檔案儲存。

可以看出,vim涉及到的3種字元編碼之間的轉換: 

讀:fileencoding—–> encoding 

顯:encoding ——> termencoding 

寫:encoding ——-> fileencoding

只要這三種轉換都不會出現問題,那麼vim就可以正常工作,不會出現亂碼。 

然而,並不是所有的字元編碼之間都能夠無損轉換,例如gbk字元編碼轉換為ascii編碼時,由於ascii並不能完全包含gbk的字元,所以會出現問題。

3 常見亂碼情況分析

3.1 讀檔案時,vim探測fileencoding不準確

這很好理解,比如以gbk編碼方式儲存的檔案,vim把fileencoding探測成了ascii,則肯定會出現問題。

【解決方法】一是靠vim自身提高探測水平;二是設定合適的fileencodings變數,把最可能用到的編碼方式放到最前面。如果vim實在是探測不對,那麼就只能通過 :set fileencoding=*** 命令來手動探測了。

3.2 fileencoding編碼無法正確轉換到encoding編碼

例如,檔案採用gbk編碼,而ecoding使用ascii,這樣大量的漢字字元無法被轉換,從而導致亂碼。 

【解決方法】把encoding設定成utf-8,目前為止utf-8能包含所有字元,所以其他的任何編碼方式都可以無損的轉換為utf-8。

3.3 encoding無法正確轉換到termencoding

這個問題,與3.2類似。 

【解決辦法】把termencoding設定為何encoding相同。預設termencoding=」「的情況下,這兩者就是相同的。

3.3 termencoding與實際的終端字元編碼不一致

例如本來字元終端的編碼屬性為gbk,而termencoding卻為utf-8,那麼vim就會錯誤的認為終端就是utf-8編碼的,導致向終端輸出utf-8編碼的位元組流,而終端卻按照gbk來識別,當然就會識別成亂碼。 

【解決辦法】把終端實際的編碼方式和vim的termencoding統一起來。

3.4 終端顯示能力欠缺

例如,傳統的字元終端,本身不具備顯示漢字的能力,雖然它可以識別出utf-8編碼的漢字,但是渲染引擎無法正確繪製,也就顯示成了亂碼。 

【解決辦法】盡量還是使用putty等偽終端軟體,避免直接使用字元終端裝置;如果實在不能避免,就要避免使用ascii字符集以外的字元,好好學習英文吧。

4 杜絕亂碼的最佳實踐

所有編碼統統設定為utf-8。這樣既能夠識別人類所有語言,又避免了各種編碼之間轉換的效能損失。

4.1 vim設定

set encoding=utf-8

set termencoding=utf-8

set fileencodings=utf-8,gbk,latin112

3如果無特殊要求和限制,磁碟檔案也以utf-8方式儲存。

C 編碼規則

c 編碼規則 一 命名 1.用pascal規則來命名方法和型別.public class textbox public void databind 2.用camel規則來命名區域性變數和方法的引數.string username public adduser string userid,byte p...

C 編碼規則

一 命名 1.用pascal規則來命名方法和型別.public class textbox public void databind 2.用camel規則來命名區域性變數和方法的引數.string username public adduser string userid,byte password...

POST編碼規則

這是乙個post資料編碼和解碼的函式 pragma warning disable 4786 include include include include using namespace std 編碼 const string post encode const string const iter...