關於漢字、亂碼和其他

原問題如下:

以下是回答:

關於編碼和亂碼的問題,我簡單講一下。

通常問這類問題的人是混淆了若干個不同的概念,並且他們自己也沒有意識到自己混淆了這些概念的。

  1. 終端顯示字元的編碼(windows下終端是cmd,linux下是各種terminal,遠程登錄是putty或者xshell)
  2. shell環境的編碼。比如中文版windows用的是gbk(向下兼容gb2312),大多數linux發行版使用的是utf-8(LANG=zh_CN.UTF-8)。
  3. 文本文件的編碼。這個通常取決於你的編輯器,而且有的編輯器支持多種編碼的話,你可以在文本開頭位置指定編輯器使用特定編碼。比如# -*- coding: utf8 -*-,vim看到這行會默認將這個腳本認定為utf-8兼容編碼格式。
  4. 應用程序的內部編碼。一個字元串,作為數據只是一個位元組數組,但是作為字元的數組,就有一個解析方式。java和python的內部字元編碼是utf-16,python和java都支持用不同的編碼來對位元組數組進行decode來得到字元數組。

拿題主的問題來解釋一下。

我在ubuntu kylin中文環境下默認terminal中做了同樣的實驗,但是結果和題主恰好相反:

看見沒有?

題主和我都沒有說謊,這是為什麼呢?

因為

unicode("漢字","gb2312")n

這坨代碼的含義實際上是:將這裡顯示的這坨看上去像「漢字」的東西,用gb2312解碼,轉換為unicode字元串。unicode("漢字","utf-8")類似,只不過是用utf-8解碼,轉成unicode字元串。

(註:這裡涉及到兩個概念——unicode字符集和utf-8編碼——很多時候會用混淆,一個字符集表示一堆符號,而一種編碼是用二進位表示這個字符集的一種編碼方式。同樣是unicode字符集,可以有utf-8、utf-16、utf-32等等編碼方式。)

那這裡顯示的看上去像「漢字」的,到底是個什麼東西?

  1. 如果是在我的環境下,也就是linux utf-8環境下一個utf-8顯示終端,能顯示成「漢字」的這坨東西,它實際上是以utf-8編碼的「漢」字和「字」字兩個unicode字元。它們的真實字元值就是u漢字(內碼),可以用"漢字".encode("hex")來查看當前終端下(utf-8編碼值)的十六進位碼。

    。所以我的命令是,將e6b189e5ad97這坨位元組數組,轉換為unicode的字元數組。——結果毫無難度,沒有錯誤,因為它本來就是utf-8編碼,所以能夠正常作為unicode字元解碼。

    但是unicode("漢字", "gb2312")就不一樣了,這個命令等同於「將e6b189e5ad97這坨東西,用gb2312編碼方式來解碼成字元」,但是實際上由於編碼空間並不兼容,使用gb2312編碼方式無法解碼這麼一坨奇葩的數據,所以葛屁了。
  2. 在題主的環境下,因為系統終端和默認文件編碼都是GBK,所以這個數實際上是

    這個實際上是gbk(兼容gb2312)的字元「漢字」的真實位元組數組。

    所以對這坨數據做unicode("漢字","utf8")會失敗——因為不管你怎麼想,雖然看上去是一樣,但是實際上不是同一坨東西啊!
  3. 題主現在弄了一個文件,在開始加上了

    # -*- coding: utf8 -*-

    這下編輯器看到了,知道這文件是utf-8的了。所以編輯器對讀入的一坨坨位元組用utf-8來解碼,對於輸出到磁碟的漢字也用utf-8來編碼。所以你在文件裡面看到的看上去像「漢字」的東西,就和第一種情況下想同了,當然代碼就跑得通。

    順便說一下,如果編輯器無視行首這行編碼聲明,或者編輯器無法支持utf-8格式,那麼你弄好的文件在那個編輯器下就會顯示亂碼,多麼簡單的道理啊。

所以,要能夠正常的顯示中文(或者其他什麼亂七八糟奇葩的多位元組文字),以下條件缺一不可:

  1. 終端和環境的編碼一致(本機通常是一致的,不一致常常出現在遠程登錄);如果不一致就需要有編輯器或者文本閱讀器做一個兼容兩者的轉換。
  2. 編輯器能夠認識文本編碼
  3. 系統擁有能顯示這種字元的字體。

這也就是我為什麼一直反對在程序文本中使用除ascii之外的所有編碼字元的原因。環境太複雜了,繞開問題遠比解決問題輕鬆。

原問題:Python2.7 中文字元編碼,使用Unicode時,選擇什麼編碼格式? - Kenneth 的回答
推薦閱讀:

人機對戰初體驗:Python實現四子棋遊戲
GitHub排第一的語言為什麼是js?
學習編程感覺吃力怎麼辦?
為什麼你需要知道介面的基本原理
200行代碼實現web框架(三):動手寫個模板引擎

TAG:Python | 中文乱码 | 编程 |