第三階段應用層——1.2 數碼相冊—字符編碼

數碼相冊——字符編碼

  • 硬件平臺:韋東山嵌入式Linxu開發板(S3C2440.v3)
  • 軟件平臺:運行於VMware Workstation 12 Player下UbuntuLTS16.04_x64 系統
  • 參考資料:《嵌入式Linux應用開發手冊》、《嵌入式Linux應用開發手冊第2版》
  • 開發環境:Linux 3.4.2內核、arm-linux-gcc 4.3.2工具鏈

目錄

  • 數碼相冊——字符編碼



作者:科言君
鏈接:https://www.zhihu.com/question/20152853/answer/95576659
來源:知乎
著作權歸作者所有,轉載請聯繫作者獲得授權。

在開發過程中,字符編碼始終是程序猿和程序媛們繞不開的一個話題。這裏簡要整理下有關字符編碼的知識,供列位看官茶餘飯後消遣:)

本回答儘量直觀地介紹相關概念,不糾纏相關規定的細節,以使讀者能對字符編碼有着更直觀的理解。當然,這樣很容易掛一漏萬,難免出現紕漏,也望各位批評指正。

衆所周知,在計算機的世界,所有的信息都是0/1組合的二進制序列,計算機是無法直接識別和存儲字符的。因此,字符必須經過編碼才能被計算機處理。字符編碼是計算機技術的基礎,也是程序猿/媛需要的基本功之一。

在展開具體介紹之前,首先要強調一下幾個概念,這對理解字符編碼非常重要,也將貫穿在後文的介紹之中:

1)
理解字符集字符編碼的區別

2)
“系統/終端/文件/程序”不同概念上的編碼

3)
常見操作系統、文本編輯器對字符編碼的處理


1 、字符集與字符編碼

如前所述,字符只有按照一定規則編碼,最終表示爲0/1二進制序列的形式,才能被計算機處理。那麼,怎麼定義這種編碼映射呢?其實很簡單,只要大家都按照相同的規則,規定好字符與二進制序列(表現爲某個數值)之間的對應關係即可。比如,我們規定英語大寫字母A對應數字65,那麼我們只要將65的二進制形式(01000001)保存即可。

那麼,問題又來了。如果大家使用的規則不一致怎麼辦,那豈不全亂套了?這時候,字符集就粉墨登場了。所謂字符集,直觀上講,就是人們統計預先規定好的一系列字符與二進制序列(數字)之間的映射關係。只要大家都遵循這個規則,並且計算機也按照這種方式處理,那麼這個世界不就很美好了!然而,全世界的語言實在太多了,由於歷史和地域的原因,也就形成了多套應用於不同場合、語言的字符集,如ASCII、GBK、Unicode等。

需要注意的是,我們規定好了字符與數字之間的對應關係,但這並不代表計算機一定要按照字符對應的數字將數字本身直接存儲!有時候,我們按照一定的規則,將字符的碼元再次處理,以更加適應計算機存儲、網絡傳輸的需要。字符編碼便是規定了如何編碼、存儲這些字符對應的二進制序列。

因此,某種意義上,可以理解爲,字符集是一種協議,而字符編碼是對字符集的一種實現。當然,既然稱之爲“實現”,也說明對同一種字符集可能有不同的編碼方式。可以想到,最直接的編碼方式,便是直接使用字符對應的二進制序列,這就導致了字符集和字符編碼看起來像是一個東東,長期受此思維影響,可能就會對Unicode和UTF的區別有些困惑。


2 、祖先:ASCII編碼

再次回顧,在計算機內部,所有的信息最終都表示爲一個二進制的序列。每一個二進制位(bit)有0和1兩種狀態,因此八個二進制位就可以組合出256(2^8)種狀態,這被稱爲一個字節(byte)。也就是說,一個字節一共可以用來表示256種不同的狀態,每一個狀態可以對應一個符號,就是256個符號,從0000_0000到1111_1111。

上個世紀60年代,美國製定了一套字符編碼,對英語字符與二進制位之間的關係,做了統一規定,這就是ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼),一直沿用至今。

ASCII碼一共規定了128個字符的編碼,包含常見的英語字符和一些控制符號。比如空格(Space)對應32(二進制0010_0000),大寫字母A對應65(二進制0100_0001)。這128個符號(包括32個不能打印出來的控制符號),只佔用了一個字節的後面7位,最前面的1位統一規定爲0,沒有使用。

需要強調的是,ASCII便是字符集與字符編碼相同的情況,直接將字符對應的8位二進制數作爲最終形式存儲。因此,當我們提及ASCII,既表示了一種字符集,也代表了一種字符編碼,即常說的“ASCII編碼”。

ASCII表如下圖所示。

<img src="https://pic1.zhimg.com/bd3b6c7e4f432b6dfbf5838f8e62cd14_b.png" data-rawwidth="535" data-rawheight="377" class="origin_image zh-lightbox-thumb" width="535" data-original="https://pic1.zhimg.com/bd3b6c7e4f432b6dfbf5838f8e62cd14_r.png">


1 ASCII編碼表(摘自百度)


3 、擴展:擴展ASCII

英語用128個符號編碼就夠了,但是用來表示其他語言,128個符號是不夠的。同時,1byte中我們不是還有最高位沒有使用麼?這能夠再編碼128個符號啊!於是,一些歐洲國家就決定,利用閒置的最高位編入新的符號。這樣一來,這些歐洲國家使用的編碼體系,可以表示最多256個符號。從128到255這些字符集被稱“擴展字符集”。基於此,ISO 組織在ASCII碼基礎上又制定了一系列標準用來擴展ASCII編碼,它們是ISO-8859-1~ISO-8859-15,其中ISO-8859-1(又稱Latin-1)涵蓋了大多數西歐語言字符,所有應用的最廣泛。ISO-8859-1仍然是單字節編碼,它總共能表示256個字符。

但是,問題又來了。。。不同的國家有不同的字母,因此,哪怕它們都使用256個符號的編碼方式,代表的字母卻不一樣。但是不管怎樣,所有這些編碼方式中,0-127表示的符號是一樣的,不一樣的只是多了128-255的這一段,因此它們都向下兼容ASCII編碼。

同樣,對於擴展ASCII,它也是既表示了字符集,也代表一種字符編碼。


4 、中文:GB系列

字符型語言的字符數量較少,因此用一個byte(8bit)基本就夠用了,這就難爲了我們博大精深的中文漢字——中文常用字就有好幾千呢!但這也難不倒我們勤勞勇敢的中國人,爲此,我們設計了GB2312字符集,意氣風發走進那新時代。

GB2312的思想其實很簡單——既然1個byte不夠用,那咱們用2個呀!正所謂,“沒有1byte解決不了的問題,如果有,就2byte”。理論上,2個字節便可以表示2^16=65536的字符。不過,GB2312最初被設計時,只規定了中文常見字,很多特殊字符還沒有包含。GB2312一共收錄了7445個字符,包括6763個漢字和682個其它符號。除了GB2312,還有用於中文繁體的Big5。

人們逐漸發現,GB2312規定的字符太少,甚至有些國家領導人名字中的漢字都表示不出來,這還了得!於是1995年的漢字擴展規範GBK1.0(《漢字內碼擴展規範》)收錄了21886個符號,它分爲漢字區和圖形符號區。GBK編碼是GB2312編碼的超集,向下完全兼容GB2312,同時GBK收錄了Unicode基本多文種平面中的所有CJK漢字。GBK還收錄了GB2312不包含的漢字部首符號、豎排標點符號等字符。

2000年的GB18030是取代GBK1.0的正式國家標準。GB18030編碼向下兼容GBK和GB2312
GB18030收錄了所有Unicode3.1中的字符,包括中國少數民族字符。GB18030雖然是國家標準,但是實際應用系統中使用的並不廣泛。目前使用最廣的仍是GBK編碼。

GBK和GB2312都是雙字節等寬編碼,如果算上爲與ASCII兼容所支持的單字節,也可以理解爲是單字節和雙字節混合的變長編碼。GB18030編碼是變長編碼,採用單字節、雙字節和4字節方案,其中單字節、雙字節和GBK是完全兼容的,4字節編碼的碼位就是收錄了CJK擴展A的6582個漢字。

從ASCII、GB2312、GBK到GB18030,這些編碼方法是向下兼容的,即同一個字符在這些方案中總是有相同的編碼,後面的標準支持更多的字符。在這些編碼中,英文和中文可以統一地處理,區分中文編碼的方法是高字節的最高位不爲0。GB2312、GBK都屬於雙字節字符集 (DBCS)。

最後,不嚴格的說,GB系列編碼也可以認爲是具有字符集的意義,又有字符編碼的意義。實際上,GB系列編碼中有“區位碼”的概念(由於採用兩個數來編碼漢字和中文符號。第一個數稱爲“區”,第二個數稱爲“位”,所以也稱爲區位碼),實際上, 區位碼更應該認爲是字符集的定義,定義了所收錄的字符和字符位置,而GB2312是實際計算機環境中支持這種字符集的編碼。區位碼和GB2312編碼的關係有點像 Unicode和UTF-8,正是最開始介紹的字符集與字符編碼的區分。


5、 統一:Unicode

介紹完ASCII、Latin和GBK,想必各位會有這樣的想法:爲什麼不規定一種字符集、編碼方式,直接能夠囊括全世界所有語言文字的符號呢?

由於科技發展不同步等歷史原因,多種編碼方式並存是不可避免的現象,但大一統的工作實際上人們也在做,這就是大名鼎鼎的Unicode。

這裏面也有段有趣的歷史。實際上,最早是由兩個獨立的組織都在設計一種通用字符集,但兩家很快意識到,這個世界並不需要兩套不同的通用字符集存在,否則所謂的“通用”便失去了意義。於是,後期的Unicode工作被有組織的統一了起來。

Unicode是爲了整合全世界的所有語言文字而誕生的,全稱是Universal Multiple-Octet Coded Character Set,它所規定的字符集也被稱爲Universal Character Set (UCS)。

再次提醒,Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。也即,UCS規定了怎麼用多個字節表示各種文字,而怎樣存儲、傳輸這些編碼,則是由UTF (UCS Transformation Format)規範規定的。UTF會在後文介紹。


5.1 UCS

UCS有兩種不同的規定版本:UCS-2和UCS-4。顧名思義,UCS-2就是用2個字節編碼,UCS-4就是用4個字節(實際上只用了31位,最高位必須爲0)編碼。因此,UCS-2有2^16=65536個碼位,UCS-4有2^31=2147483648個碼位。目前UCS-2已經足夠用了,UCS-4估計都可以把Asgard和氪星的文字(傳說都是英語?)也收錄進來了……具體的符號對應表,可以查詢unicode.org,或者相關的字符對應表。

UCS-4根據最高位爲0的最高字節分成2^{7}=128個Group,每個Group再根據次高字節分爲256個Plane,每個Plane根據第3個字節分爲256行 (Rows),每行包含256個Cells。同一行的Cells只是最後一個字節不同,其餘都相同。


<img src="https://pic4.zhimg.com/e372ce8d8d819bc20b72d3490e07314b_b.png" data-rawwidth="577" data-rawheight="43" class="origin_image zh-lightbox-thumb" width="577" data-original="https://pic4.zhimg.com/e372ce8d8d819bc20b72d3490e07314b_r.png">

其中,Group 0的Plane 0被稱作Basic Multilingual Plane,即BMP,或者說UCS-4中,高兩個字節爲0的碼位被稱作BMP。將UCS-4的BMP去掉前面的兩個零字節就得到了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就得到了UCS-4的BMP。而目前的UCS-4規範中還沒有任何字符被分配在BMP之外。


那麼,新的問題又來了:

1)
如何才能區別Unicode和ASCII?計算機怎麼知道2個字節表示1個符號,而不是分別表示2個符號呢?

2)
我們已經知道,英文字母只用1個字節表示就夠了(ASCII),如果Unicode統一規定,每個符號用2個或4個字節表示,那麼每個英文字母前都必然有許多字節是0,這對於存儲來說是極大的浪費,是無法接受的。

這些問題造成的結果是:

1)
出現了Unicode的多種存儲方式,也就是說有許多種不同的格式,可以用來表示Unicode。

2)
Unicode在很長一段時間內無法推廣,直到互聯網(UTF-8)的出現。


5.2 UTF

UTF(Unicode/UCS Transformation Format),即Unicode字符集的編碼標準,可以理解爲對Unicode字符集的具體使用/實現方式,主要有UTF-16、UTF-32和UTF-8。

UTF-16

UTF-16由RFC2781協議規定,它使用2個字節來表示1個字符。不難猜到,UTF-16是完全對應於UCS-2的(實際上稍有區別),即把UCS-2規定的代碼點通過Big Endian(下文介紹)或Little Endian方式直接保存下來。UTF-16包括三種:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。

UTF-16BE和UTF-16LE不難理解,而UTF-16就需要通過在文件開頭以名爲BOM(Byte Order Mark,下文介紹)的字符來表明文件是Big Endian還是Little Endian。BOM爲\uFEFF這個字符。其實BOM是個小聰明的想法。由於UCS-2沒有定義\uFFFE,因此只要出現 FF FE 或者 FE FF 這樣的字節序列,就可以認爲它是\uFEFF,並且據此判斷出是Big Endian還是Little Endian。


例:“ABC”這三個字符用各種方式編碼後的結果如下:


<img src="https://pic4.zhimg.com/fb3a32debb446172d99dddc0d0a5fc73_b.png" data-rawwidth="779" data-rawheight="156" class="origin_image zh-lightbox-thumb" width="779" data-original="https://pic4.zhimg.com/fb3a32debb446172d99dddc0d0a5fc73_r.png">

另外,UTF-16還能表示一部分的UCS-4字符——\u10000~\u10FFFF,表示算法就不再詳細介紹了。

總結來說,UTF-16以2、4字節存儲一個Unicode編碼,對於小於0x10000的UCS碼,UTF-16編碼就等於UCS碼對應的16位無符號整數。對於不小於0x10000的UCS碼,定義了一個算法。不過由於實際使用的UCS2,或者UCS4的BMP必然小於0x10000,所以就目前而言,可以認爲UTF-16和UCS-2基本相同(前提是明白UTF和UCS的差別)


UTF-32

UTF-32用4個字節表示字符,這樣就可以完全表示UCS-4的所有字符,而無需像UTF-16那樣使用複雜的算法。與UTF-16類似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三種編碼,UTF-32也同樣需要BOM字符。仍以“ABC”爲例:


<img src="https://pic1.zhimg.com/45a04ca95881e82755ff6adab07f3ae0_b.png" data-rawwidth="671" data-rawheight="137" class="origin_image zh-lightbox-thumb" width="671" data-original="https://pic1.zhimg.com/45a04ca95881e82755ff6adab07f3ae0_r.png">

UTF-16和UTF-32的一個缺點就是它們固定使用2個或3個字節,這樣在表示純ASCII文件時會有很多零字節,造成浪費。RFC3629定義的UTF-8則解決了這個問題,下面介紹UTF-8。


UTF-8

隨着互聯網的普及,強烈要求出現一種統一的編碼方式,UTF-8就是在互聯網上使用最廣的一種Unicode的實現(傳輸)方式。

UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1-4個字節表示一個符號,根據不同的符號而變化字節長度。爲什麼採用邊長的機制,實際上和字符出現的概率分佈有關,其中蘊含着Huffman編碼的思想——最常出現的字符編碼儘量的短。

UTF-8的編碼規則很簡單,如下:

1) 對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的Unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。

2) 對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一律設爲10。剩下的沒有提及的二進制位,全部爲這個符號的Unicode碼。

下表總結了編碼規則,字母x表示可用編碼的位。


<img src="https://pic4.zhimg.com/bbed856237e597044df7987bb3607d27_b.png" data-rawwidth="672" data-rawheight="163" class="origin_image zh-lightbox-thumb" width="672" data-original="https://pic4.zhimg.com/bbed856237e597044df7987bb3607d27_r.png">

可見,ASCII字符(\u0000~\u007F)部分完全使用一個字節,避免了存儲空間的浪費,而且UTF-8可以不再需要BOM字節。

另外,從上表中可以看出,單字節編碼的第一字節爲00-7F,雙字節編碼的第一字節爲C2-DF,三字節編碼的第一字節爲E0-EF,這樣只要看到第一個字節的範圍就可以知道編碼的字節數,可以大大簡化算法(感興趣的話可以自己實現編碼、解碼的算法)。

例:以漢字“嚴”爲例。

已知“嚴”的Unicode(UCS-2)碼是\u4E25(0100_1110_0010_0101),根據上表,可以發現\u4E25處在第三行的範圍內(0000 0800 ~ 0000 FFFF),因此“嚴”的UTF-8編碼需要3個字節,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然後,從“嚴”的最後一個二進制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就得到了,“嚴”的UTF-8編碼是“111001001011100010100101”,轉換成十六進制就是E4 B8 A5。

可以看到“嚴”的Unicode碼是\u4E25,而UTF-8編碼是E4 B8 A5,兩者是不一樣的。它們之間的轉換可以通過程序或一些編輯器實現。


5.3 大端、小端與字節序標記

UTF-8以單字節爲編碼單元,沒有字節序的問題。UTF-16以2個字節爲編碼單元,在解釋一個UTF-16文本前,首先要弄清楚編碼單元的字節序。例如,當我們收到6A7C時,它到底代表\u6A7C還是\u7C6A?

仍以漢字“嚴”爲例,Unicode(UCS-2)碼是\u4E25,需要用兩個字節存儲,一個字節是4E,另一個字節是25。存儲的時候,4E在前,25在後,就是Big endian方式;25在前,4E在後,就是Little endian方式。

因此,第一個字節在前,就是“大頭/大端方式”(Big endian),第二個字節在前就是“小頭/小端方式”(Little endian)。那麼很自然的,就會出現一個問題:計算機怎麼知道某一個文件到底採用哪一種方式編碼?

Unicode編碼規範中定義,每一個文件的最前面分別加入一個表示編碼順序的字符,這個字符的名字叫做“零寬度非換行空格”(Zero Width No-Break Space),它的編碼是FEFF。其實FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中,UCS規範建議我們在傳輸字節流前,先傳輸字符"Zero Width No-Break Space",這正好是2個字節,而且FF比FE大1。如果一個文本文件的頭2個字節是FE FF,就表示該文件採用大頭方式;如果頭2個字節是FF FE,就表示該文件採用小頭方式。字符"Zero Width No-Break Space"又被稱作BOM(Byte Order Mark,字節序標記)。

UTF-8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符"Zero Width No-Break
Space"的UTF-8編碼是EF BB BF,所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。Windows就是使用BOM來標記文本文件的編碼方式的,但實際上並不建議UTF-8格式的文件使用BOM。


6 、各種環境下的編碼

簡單介紹完字符編碼相關知識後,我們需要理解不同環境下的字符編碼問題,這對程序猿/媛們來說更爲重要。談及具體環境下的編碼,我們實際上有以下四個層次:

1)
操作系統默認編碼方式。這是操作系統的內部屬性,比如大多Linux系統、Mac OS默認UTF-8編碼,中文版Windows系統默認GBK編碼

2)
終端編碼方式。終端包括cmd、shell、terminal等,在與終端交互時,字符是要在終端顯示的,這必然涉及到終端採用的編碼方式,事實上有不少bug是在這個層面產生的。對於單機系統而言,終端編碼與操作系統編碼一般是一致的,但在遠程登錄時,可能會遇到一些問題。

3)
文本文件的編碼方式。這是我們接觸最多的概念,即一個文本文件(如源代碼文件)是以什麼編碼格式保存的。大多數編輯器可以顯示文本的編碼格式,以及更改編碼方式重新存儲。以下圖中的Notepad++編輯器爲例,在格式選項卡中顯示了可以進行編碼轉換的選項。

4)
程序中的字符、字符串變量的編碼方式。這與具體的編程語言相關,涉及到程序運行時變量在內存中的狀態。Python典型的encode/decode就是這個鬼。

<img src="https://pic3.zhimg.com/aa4ead31d2e48a79fdebfc3be32369ea_b.png" data-rawwidth="224" data-rawheight="221" class="content_image" width="224">


2 Notepad++中的編碼選項

以Java和Python編程語言爲例。

Java和Python3裏,字符均採用Unicode編碼(Java.lang.String 採用 UTF-16 編碼方式存儲所有字符),因此可以很好地支持中文。但是,Python2中Unicode不是字符默認編碼格式(Python從2.2纔開始支持Unicode),因此需要進行編碼的轉換。函數decode( char_set )可以實現其它編碼到Unicode的轉換,函數encode( char_set )可以實現Unicode到其它編碼方式的轉換,這裏所講的Unicode String是指 UCS-2或者UCS-4 編碼的Code Points。

比如, ("你好").decode(
"GB2312") 將得到 u'\u4f60\u597d',即“你”和“好"的 Unicode 碼分別是0x4f60 和 0x597d,再用
(u'\u4f60\u597d').encode("UTF-8") 就可以得到“你好”的UTF-8編碼結果:'\xe4\xbd\xa0\xe5\xa5\xbd'。【請注意,這些運行結果跟具體的操作平臺有關,讀者可以思考爲什麼,相關解答可以參考知乎(Python2.7 中文字符編碼,使用Unicode時,選擇什麼編碼格式? - Kenneth 的回答)對此的解釋,本小節也是受到該回答的啓發整理而成】


<img src="https://pic4.zhimg.com/adca7b41a0e6c24897111ca9dcffb627_b.png" data-rawwidth="396" data-rawheight="206" class="content_image" width="396">

圖 3 Unicode decode/encode in Python (摘自Nature Language Processing with Python, 2 edition)

實際上,Python 3和2很大區別就是Python本身改爲默認用Unicode編碼。字符串不再區分"abc"和u"abc",字符串"abc"默認就是Unicode,不再代表本地編碼,由於有這種內部編碼,與C#和Java類似,沒有必要在語言環境內做類似設置編碼,也因此Python 3的代碼和包管理上打破了和2.x的兼容。

再次提醒:只有字符到字節或者字節到字符的轉換才存在編碼轉碼的概念


7、 編碼總結

總結一下上述內容:

1、編碼界最初只有ASCII碼,只用了1byte中的7bit(0~127);

2、歐洲人發現128個不夠了,就把1byte中沒用的最高位給用上了,出現了Latin系列(ISO-8859系列)編碼;

3、中國人民通過對ASCII編碼進行中文擴充改造,產生了GB2312編碼,可以表示6000多個常用漢字;

4、漢字實在太多了,還有繁體、各種字符呀,於是加以擴展,有了GBK;

5、GBK還不夠,少數民族的字還木有呀,於是GBK又擴展爲GB18030;

6、每個國家、語言都有自己的編碼,彼此無法交流,迫切需要大一統局面的出現;

7、Unicode誕生,可以容納全世界的任何文字。Unicode分爲UCS-2和UCS-4,分別是2字節和4字節,實際2字節就夠用了;

8、爲了Unicode能實際應用(存儲、傳輸),制定了Unicode的編碼方式,即UTF,有UTF-8、UTF-16、UTF-32,其中UTF-8應用廣泛;

9、UTF-16、UTF-32均是多字節傳輸,存在字節順序的問題,於是有了大頭還是小頭的概念,爲了解決這個問題,引入了BOM。UTF-8是單字節傳輸,不存在這個問題,也就不需要BOM,但可以有,僅用來表明編碼格式;

10、要從“環境/終端/文本/程序”等不同層次去理解編碼,並嘗試解決遇到的問題;


8 、最後的叨叨唸

各種編碼方式的不一致,環境平臺的不一致,會導致在編程中遇到各種頭疼的bug。如果對這些相關的概念有一定的瞭解,至少在解決問題時會從容很多。

爲了最大程度上減少可能產生的問題,可以在平時多注意一些細節,一方面方便個人開發,另一方面減少對二次開發用戶的干擾。比如:

1)
可以的話,文本儘量以UTF-8(無BOM)方式存儲。對於Windows用戶,強烈建議棄用默認的文本編輯器,採用一款更專業的編輯器,並將默認編碼格式設置爲UTF8(無BOM)。

2)
跨平臺開發時,如果需要在terminal輸出,注意terminal的編碼方式,有時採用重定向到文件會是一個更加通用的選擇。

3)
對於Python用戶,如果不是相關依賴項只有py2版本,強烈建議採用py3開發,會減少很多中文相關的問題。

4)
路徑、文件、變量等按照規範命名。比如,聽說Java支持用中文命名變量了,因此可能會出現這樣的代碼,String 哈哈 = "2333333"; 爲了減少後續可能遇到的問題,奉勸還是不要這樣,不做死就不會死。

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