Vim打開中文文件亂碼

Vim有四個跟字符編碼方式有關的選項,encoding、fileencoding、fileencodings、termencoding(這些選項設置請參考Vim文檔中encoding-names章節),它們的意義如下:

  • encoding
    encoding是Vim內部使用的字符編碼方式,包括Vim的buffer(緩衝區)、菜單文本、消息文本等。默認是根據你的locale選擇。VIM用戶手冊上建議只在.vimrc中改變它的值,事實上似乎也只有在.vimrc中改變它的值纔有意義。你可以用另外一種編碼來編輯和保存文件,如你的vim的encoding爲utf-8,所編輯的文件採用cp936編碼,vim會自動將讀入的文件轉成utf-8(vim的能讀懂的方式),而當你寫入文件時,又會自動轉回成cp936(文件的保存編碼)。
  • fileencoding
    Vim中當前編輯的文件的字符編碼方式,Vim保存文件時也會將文件保存爲這種字符編碼方式(不管是否新文件都如此)。
  • fileencodings
    Vim自動探測fileencoding的順序列表,啓動時會按照它所列出的字符編碼方式逐一探測即將打開的文件的字符編碼方式,並且將 fileencoding 設置爲最終探測到的字符編碼方式。因此最好將Unicode 編碼方式放到這個列表的最前面,將拉丁語系編碼方式 latin1放到最後面。
  • termencoding
    Vim所工作的終端(或者 Windows的Console窗口)的字符編碼方式。如果vim所在的term與vim編碼相同,則無需設置。如其不然,你可以用vim的termencoding選項將自動轉換成term的編碼.這個選項對GUI模式Vim(GVim)無效,而對Console模式的Vim而言就是Windows控制檯的代碼頁,並且通常我們不需要改變它。

現在來看看Vim的多字符編碼方式支持是如何工作的:

  1. 啓動Vim,根據.vimrc文件中設置的encoding的值來設置buffer、菜單文本、消息文的字符編碼方式。
  2. 讀取需要編輯的文件,根據fileencodings中列出的字符編碼方式逐一探測該文件編碼方式。並設置fileencoding爲探測到的,看起來是正確的字符編碼方式。
  3. 對比fileencoding和encoding的值,若不同則調用iconv將文件內容轉換爲encoding所描述的字符編碼方式,並且把轉換後的內容放到爲此文件開闢的 buffer 裏,此時我們就可以開始編輯這個文件了。注意,完成這一步動作需要調用外部的 iconv.dll,你需要保證這個文件存在於$VIMRUNTIME或者其他列在PATH環境變量中的目錄裏。
  4. 編輯完成後保存文件時,再次對比fileencoding和encoding的值。若不同,再次調用iconv將即將保存的buffer中的文本轉換爲fileencoding所描述的字符編碼方式,並保存到指定的文件中。同樣,這需要調用iconv.dll由於Unicode能夠包含幾乎所有的語言的字符,而且Unicode的UTF-8編碼方式又是非常具有性價比的編碼方式 (空間消耗比 UCS-2 小),因此建議encoding的值設置爲utf-8。這麼做的另一個理由是encoding設置爲 utf-8 時,Vim 自動探測文件的編碼方式會更準確 (或許這個理由纔是主要的 ;)。我們在中文Windows裏編輯的文件,爲了兼顧與其他軟件的兼容性,文件編碼還是設置爲GB2312/GBK比較合適,因此fileencoding建議設置爲chinese(chinese是個別名,在Unix裏表示gb2312,在Windows裏表示cp936,也就是GBK的代碼頁)。

當vim在utf-8的local下打開gbk文件時,顯示的是亂碼,可以在~/.vimrc文件中加入如下代碼來解決:

set fencs=utf-8,gbk

這一行的作用是告訴vim,打開一個文件時,嘗試utf8,gbk兩種編碼,vim只需要掃描文件的前一段,就可以根據文件裏面的數據判斷出文件是否用的是utf8或者gbk編碼。如果不指定這一行,則vim只會用當前編碼 (locale)來打開文件,因爲locale是UTF-8,而文件是gbk,所以打開是亂碼。

一般vim打開中文文件時出現亂碼時可以用下面的方法來解決:

set fileencoding=gb18030 set fileencodings=utf-8,gb18030,utf-16,big5

這樣設置的原因說明如下:vim裏面的編碼主要跟三個參數有關:enc(encoding), fenc(fileencoding)和fencs(fileencodings)。其中fenc是當前文件的編碼,也就是說,一個在vim裏面已經正確顯示了的文件(前提是你的系統環境跟你的enc設置匹配),你可以通過改變 fenc後再w來將此文件存成不同的編碼。比如說,我:set fenc=utf-8然後:w就把文件存成utf-8的了,:set fenc=gb18030再:w就把文件存成gb18030的了。這個值對於打開文件的時候是否能夠正確地解碼沒有任何關係。fencs就是用來在打開文件的時候進行解碼的猜測列表。文件編碼沒有百分百正確的判斷方法,所以vim只能猜測文件編碼。比如我的vimrc裏面這個的設置是:

set fileencodings=utf-8,gb18030,utf-16,big5

所以我的vim每打開一個文件,先嚐試用utf-8進行解碼,如果用utf-8解碼到了一半出錯(所謂出錯的意思是某個地方無法用utf-8正確地 解碼),那麼就從頭來用gb18030重新嘗試解碼,如果gb18030又出錯(注意gb18030並不是像utf-8似的規則編碼,所以所謂的出錯只是 說某個編碼沒有對應的有意義的字,比如0),就嘗試用utf-16,仍然出錯就嘗試用big5。這一趟下來,如果中間的某次解碼從頭到尾都沒有出錯,那麼 vim就認爲這個文件是這個編碼的,不會再進行後面的嘗試了。這個時候,fenc的值就會被設爲vim最後採用的編碼值,可以用:set fenc?來查看具體是什麼。

當然這個也是有可能出錯的,比如你的文件是gb18030編碼的,但是實際上只有一兩個字符是中文,那麼有可能他們正好也能被utf-8解碼,那麼這個文件就會被誤認爲是utf-8的導致錯誤解碼。

至於enc,其作用基本只是顯示。不管最後的文件是什麼編碼的,vim都會將其轉換爲當前系統編碼來進行處理,這樣才能在當前系統裏面正確地顯示出 來,因此enc就是幹這個的。在windows下面,enc默認是cp936,這也就是中文windows的默認編碼,所以enc是不需要改的。在 linux下,隨着你的系統locale可能設爲zh_CN.gb18030或者zh_CN.utf-8,你的enc要對應的設爲gb18030或者 utf-8(或者gbk之類的)。

最後再來說一下新建空文件的默認編碼。看文檔好像說會採用fencs裏面的第一個編碼作爲新建文件的默認編碼。但是這裏有一個問題,就是fencs 的順序跟解碼成功率有很大關係,根據我的經驗utf-8在前比gb18030在前成功率要高一些,那麼如果我新建文件默認想讓它是gb18030編碼怎麼 辦?一個方法是每次新建文件後都:set fenc=gb18030一下,不過我發現在vimrc裏面設置fenc=gb18030也能達到這個效果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章