PHP字符編碼ASCII 、GB23十二、GBK、UTF-8解釋

變量命名規則:
1.  變量名區分大小寫(case-sensitive) 。
2.  必須字母或下劃線開頭。變量名可由 字母、數字、下劃線組成。  


看 到這裏可能,不少人納悶了~。那爲啥  $我是變量    這樣的中文也能作變量名呢? 在PHP裏,中文的確是能夠作變量名的(能用是能用但千萬別項目上用....) 。 由於這裏的字母是指: a-z   A-Z  和  擴展ASCII 字符裏從 127 到 255  ,16進製表示爲:0x7f-0xff   。 那意思就是ASCII字符裏從127到255 (0x7f-0xff) 涵括了中文? 的確是這樣的。下面就簡單的講下編碼。



ASCII 、GB23十二、GBK、UTF-8  編碼:


ASCII :
ASCII 編碼裏包括了128個字符。用 十進制 0  到 127 來表示 。那就對了, 0 到 127 不就是 128個字符嗎。 每個數字都表明一個字符。看ASCII 編碼表







我 們先看十進制(Dec) 這列,看到了嗎 。 十進制數字  9 對應 的字符是 咱們開發用得最多的 TAB鍵。 再看看 48 對應的字符是  0 。沒錯從  ASCII  48開始 到57 都表示數字  0到9 。  ASCII  97 到 122 表示 小寫字母 a 到 z 。   好比: 咱們看到的字母 a  ,其實計算機並不認識啥 字母a , 她只認識  97。 她把a 轉成了 ASCII 97來進行存儲。下面用PHP 來玩玩 ASCII 。



來咱們認識兩個函數:
ord  ----  Return ASCII value of character     返回 字符的 ASCII 值 。
chr  ----  Return a specific character     返回 ASCII 對應的 字符。

翠花上例子:
<?php echo(ord('a'));?>

//輸出   97  
沒錯吧,  小寫a的 ASCII 就是  97。   要把 ASCII 97  對應的字符打印出來:
<?php echo(chr(97));?>


//輸出 a
恩。看完基本就明白了。  ASCII 編碼 裏面包括了  大小寫字母   數字 和 一些經常使用的控制字符。 這樣在使用英語的國家基本就能使用了。計算機存儲的是ASCII 。 人看到的就是 ASCII 對應的字符。

GB2312 編碼:
世界上並不全是用英語做爲語言的。好比我國用的是中文。小日本用的是 日語。 韓國用的是韓文。 這些語言和英語徹底不是一回事。 你看ASCII 表上有中文對應的」數字「嗎?沒有吧。由於還有一份 GB2312編碼表 ,和ASCII 編碼表道理同樣。  連接: http://wenku.baidu.com/view/244e2d2ce2bd960590c677a6.html     你們打開一看,哎呀~~! 是否有點亂亂,找不到頭緒,啥亂七八糟。 不過當明白原理,就容易看懂了。

在 GB2312編碼裏面,一個字符咱們須要用兩個字節來進行存儲和表示。咱們記得ASCII 編碼裏面 一個字符只須要一個字節。因此以GB2312存儲數據比 ASCII 大一倍。 那麼GB2312 這兩個字節,分別放啥數字 才能表示字母 a 呢? 咱們知道 ASCII 編碼  a  就一個字節表示,編碼97。 GB2312 編碼比 ASCII 複雜一點,


在要看懂 GB2312編碼表以前,首先咱們要學習下」區位碼「。



區位碼概念:
GB2312對漢字和其餘字符(字母,數字等)進行了「分區」。
       01-09區爲特殊符號(數字呀、字母呀等)。
       16-55區爲一級漢字,按拼音排序。
       56-87區爲二級漢字,按部首/筆畫排序。


分區是啥?好比我是廣西的,你是河南的、他是廣東。 也就是說每一個字符確定存在於某個區裏。  這種表示方式叫作 「區位碼」。  區位碼 實際上是   區號和位號(表示一個字符在這個哪一個區裏的第幾列) 。 你想知道每一個漢字的區位碼?簡單呀。給你個連接本身查去  http://www.jscj.com/index/gb2312.php      






我 們以   「啊」 這個漢字來查它的區位碼。  以上圖所示   1601  是 「啊」這個漢字的區位碼。  區號是 16 ,  位號  01。     若是你們還記得,  16區 是 一級漢字哦。牛X呀。一級漢字是啥意思? 我估計是經常使用的漢字?~我也不知道,這個是國內專家定義的。  位號 是 01   ,位號其實就是說你在這個區裏排行老幾。  有了 x軸(區號)和y軸(位號) 那麼天然就又個交點,經過交點就能在 GB2312編碼表上找到對應的漢字了。


若是你如今就去看 GB2312的編碼表,我估計你仍是看不懂,雖說經過區位碼就能定位到GB2312編碼的字符了。可是GB2312編碼表上並沒那麼單純。 還要繼續往下看。

上面咱們說的是GB2312的  區位碼: 區號和位號。   前面我說過,一個GB2312的字符 是用兩個字節來表示的:(高位字節,低位字節)。第一個字節稱爲「高位字節」 ,第二個字節稱爲「低位字節」  ps:由於高的通常排左邊吧~  因此叫 高位字節....    。
算法以下: 一個GB2312的字符  ==  (0xA0 + 區號,0xA0 + 位號)。按照這個算法,你再取看 GB2312編碼表,你就看得如魚得水了。

0xA0 是啥意思呢?  爲啥高位字節 等於 區號 加上  0xA0 。  爲啥低位字節 等於 位號 加上 0xA0呢。這樣組合起來的兩個字節就能表示一個 GB2312的字符?  沒錯,就是那麼簡單。 0xA0 是一個16進制數字  換算成 十進制其實就等於 160 。   高位字節 等於  160 加上 區號,你能夠理解爲,其實就是 GB2312編碼字符 是從 160 起步的。 就比如 ASCII 編碼是從 0開始  到  127 結束。    

咱們從新來看下算法  : 一個GB2312的字符  ==  (0xA0 + 區號,0xA0 + 位號) 。
以 上所看,只要咱們知道 區位碼(區號和位號)就能算出一個漢字的GB2312編碼數字。 字母a 的區位碼 : 0365 ,也就是區號 03   位號 65 。  按照上面算法咱們算下。 把 0xA0 換成十進制  等於 160。 也就是 (160+03,160+65)    等於   (163,225) 換成 16進制(編碼表通常都是16進制)  (A3,E1) 。   OK了。   字母a 的gb2312編碼 出來了,拿着   A3E1去  GB2312編碼表去找這個16進制數字對應的字符吧。 若是你沒看錯的話,沒錯就是對應着 編碼表上的字母 a 。  
因此, 只要記得 上面公式, 找個工具算出漢字區位碼,而後套進公式裏面算下。就能的到這個字符的GB2312編碼值了。  你們能夠本身動手去試試算出上面的漢字 「啊」  的GB2312的編碼值。

小總結一下,你們記住:
ASCII 編碼的範圍  --   十進制 => 0 - 127 。  十六進制: 0x00  -  0x7F 。
GB2312編碼的範圍  --   十進制 => 高位字節:161 - 247 。十六進制:0xA1 - 0xF7  , 低位字節:  161 - 254 。十六進制:0xA1 - 0xFE  。

GBK 編碼:
GB2312 之上的一種擴展編碼,GBK 編碼已經包括了GB2312編碼,並擴展了GB2312編碼,使它能表示更多的字符。  GB2312和GBK 原理同樣,他們區別只是,編碼值範圍不同了。 GBK 更大了。
GB2312 編碼值範圍 :   高字節從A1到F7,而低位字節從A1到FE。
GBK 編碼值範圍:  高字節從81到FE,而低位字節從40到FE 。

以上範圍能夠看出。GBK 比  GB2312大不少。   大是大了不少... 不過如今通常項目都用UTF-8編碼了。 接下來將下UTF-8編碼方式

UTF-8編碼:
世 界上那麼多國家,每一個國家的語言都不同。一會出個 ASCII 一會出個 GBK 一會出個 XXOO 編碼。那崩潰了。是否能發明一種編碼方式,能很好的表示出全部語言呢? Unicode編碼就是這樣產生的。這裏咱們只講Unicode中得一種實現方式。UTF-8,固然還有其餘的實現方式。但對於咱們WEB開發來講,並不 經常使用。


ASCII 編碼能很好的表示字母、數字等。因此UTF-8 就在它的基礎上進行了一下擴展。  按照慣例,咱們仍是先看下 Unicode編碼 表(UTF8編碼表?木有。咱們須要掌握如何從Unicode 轉換成 utf8)

學習這節的目的php

  • 掌握從Unicode 轉換成utf8編碼的方法
  • 判斷UTF-8下的字符的字節數。  看下錶:
  •  



unicode 字節位表html


unicode 編碼範圍 十進制/十六進制

UTF-8 字節模板二進制/十六進制

字節數

(0)000000 – (127)00007F

0xxxxxxx(00-7F)

一字節

(128)000080 – (2047)0007FF

110xxxxx(C2-DF)      10xxxxxx

兩個字節

(2048)000800 – (55295)00D7FF (57344)00E000 – (65535)00FFFF

1110xxxx(E0-EF)     10xxxxxx     10xxxxxx

三個字節

(65536)010000 – (1114111)10FFFF

11110xxx(F0-F4) 10xxxxxx 10xxxxxx 10xxxxxx

四個字節



這個表很重要,記下這個表就基本瞭解了UTF-8 是怎麼一回事。  UTF-8 一共能用四個字節來表示。 但通常字符呢基本用三個字節就能知足了。

一個字節等於8位。這個你們都知道。   從 00000000   -   11111111    這個就是一個字節的數值範圍。   換算成十進制就是  0  -  255 。  懂了這個咱們繼續往下講。


繼續看上圖,   咱們慢慢講:

UTF-8中之 一字節:

在UTF-8裏面對ASCII 編碼進行了保留而後再它之上進行了擴展補充。 一個字節 存的 仍是字母呀  數字呀 和ASCII 編碼同樣。因此 編碼範圍也是   0  -  127 。
有 點同窗納悶爲啥是  127 呢? 一個字節換算成二進制不是 255嗎?  由於一字節的時候,第一位給借去了,第一位的值爲 固定爲0   。你們看上圖第一行 「UTF-8字節模板「 這一列 就明白了。因此其實只有7位是用來表示字符。那麼 換算了下 7位  的二進制 就只有   0  -  127  了。 這個幾乎和ASCII 編碼同樣,  想知道0  -  127 都分別對應了什麼字符? 看ASCII 編碼表呀。

UTF-8 之兩字節:
一 個字節 8位,兩個字節就16位了。哇!值更大了,能表示的字符更多了。因此什麼希臘字母呀、拉丁字母呀等均可以用兩字節來表示了。 看 第二行的 」UTF-8字節模板「 這一列 。110xxxxx      10xxxxxx          一共有16位, 每8位一個字節。 你們知道,在一個字節的時候,第一位是不能用的。  兩個字節的時候稍微不一樣了。 在兩個字節的時候, 第一個字節的前三位給借去了,同時第二個字節的前兩位也是給借去了。    恩在這裏,咱們只要明白一個地方就行。   UTF-8 編碼中 當字符是兩個字節表示的時候,第一個字節的編碼值範圍是多少?    第一個字節是 : 110xxxxx   。   那麼也就是範圍從   11000000  -  11011111     換成十六進制範圍是   C2  -   DF  。   恩懂這一點,就足夠了。  之後遇到 寫 UTF-8編碼 下的 截取 函數 、統計長度函數 就不用怕了。



UTF-8 之三字節:
三 個字節表示,是咱們用的最多的,由於俺們寫中文的嘛。  不過這裏注意下就是 ,三字節下的借位狀況。  繼續看上圖 。   1110xxxx(E0-EF)     10xxxxxx     10xxxxxx     看到了嗎?你懂的~ 若是還不懂...仍是繼續重頭看起吧。  UTF-8 下 一個字符三字節的。  第一個字節 的範圍是多少? 這個必須弄清楚。 範圍是從   11100000  -  11101111   十六進制是: E0   -  EF  。  



UTF-8 之四字節:
這個遇到真很少。 不過道理  你真懂了。我就不說了

好了。咱們完成了一個目標了 : 判斷UTF-8下的字符的字節數。好比之後開發你遇到:
對 於這段文字 :  "逆雪寒之PHP拾遺"        。 我要在UTF-8下統計它的字符長度  和  實現截取字符竄。   應該沒那麼心慌了。  固然有人說,統計字符長度和截取中文字符竄不是很簡單嗎?mb_strlen 、 mb_substr 。 的確是能夠呀。 但我想咱們要知其然知其因此然 。 咱們的目標是 PHP產品級研發。 不是 PHP企業網站級研發  -_-! 。



接下來完成另一個目標: 掌握從Unicode 轉換成utf8編碼的方法


我 們繼續看 unicode 字節位表  。 看第一列    unicode 編碼範圍 。 四個字節,因此就有四個範圍 。 看這個  (0)000000 – (127)00007F       十進制從 0 開始到  127  。這個就是第一字節的unicode 範圍。  其餘的也是同一個意思。
明白了上面講的之後,如今開始講 unicode 編碼轉換 UTF-8的流程:

咱們用 「啊」 這個漢字爲例,它的 Unicode 編碼是  U+554A (怎麼知道的?查 unicode 編碼表呀 大哥...) 。 而後咱們轉成UTF-8 :正則表達式

  • U+554A 換成十進制是  21834  。 比對  上面的  unicode 字節位表 的第一列  。看到  21834 是在  三個字節的  (2048)000800 – (55295)00D7FF  範圍以內。  由於  「啊」  在UTF-8 裏是三個字節的。



  • 三個字節 的UTF-8模板  是(看 unicode 字節位表 )   1110xxxx      10xxxxxx     10xxxxxx      。



  • "啊「  的   U+554A換算成二進制是 : 1010  101010 01010



  • 把15位二進制按照順序的填入(不足最後補0)  三字節的 UTF-8 模板裏面  。也就是    11101010  10101010  10010100   。    第三字節 不足位,因此最後補0.



  • 最後結果 ,0xEA  0xAA  0x94  這三個就是 」啊「  字的UTF-8編碼了。




附送: Unicode  編碼表  http://wenku.baidu.com/view/01a4feeae009581b6bd9ebe1.html      




終 於講完了編碼。。。 那麼回過頭來。。講了那麼多廢話就是爲了解釋。 爲啥 PHP能用中文來作變量名。 PHP官方文檔給的 變量名正則表達式'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' 。 裏面的\x7f \xff 我想你們都明白了吧。。。 \x7f - \xff 的十進制是: 127 - 255。 那麼按照咱們以前上面講的那些 編碼規則~ 每一個字節的編碼 都是在 127 - 255範圍以內對吧?除了一字節。 那麼也就是說 中文不管是GBK GB2312 仍是UTF-8編碼的, 用來作變量名都是符合了'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' 這條正則的。 接下來咱們也不要浪費了前面所學了哪些編碼知識。。咱們要應用,咱們要深刻了解...因此開始寫兩個函數,估計你們都在開源的代碼。好比啥 phpcms 啥 uchome discuz 裏面 看到過相似這些函數。沒錯~~! 理解完上面的編碼知識。我相信 這些對你來講~~ 小菜一碟...算法

  1. //截取字符串字串-GBK (PHP)        
  2. function  gb_substr( $str ,  $len ){        
  3.       $count  = 0;        
  4.       for ( $i =0;  $i < strlen ( $str );  $i ++){        
  5.           if ( $count  ==  $len )  break ;        
  6.           if (preg_match( "/[\x80-\xff]/" ,  substr ( $str ,  $i , 1))) ++ $i ;        
  7.            ++ $count ;                
  8.      }        
  9.       return   substr ( $str , 0,  $i );        
  10. }

 

    1. //統計字符串長度-UTF8 (PHP)        
    2. function  utf8_strlen( $str ) {        
    3.       $count  = 0;        
    4.       for ( $i  = 0;  $i  <  strlen ( $str );  $i ++){        
    5.           $value  = ord( $str [ $i ]);        
    6.           if ( $value  > 127) {      
    7.               if ( $value  >= 194 &&  $value  <= 223)  $i ++;        
    8.               elseif ( $value  >= 224 &&  $value  <= 239)  $i  =  $i  + 2;        
    9.               elseif ( $value  >= 240 &&  $value  <= 247)  $i  =  $i  + 3;        
    10.               else   die ( 'Not a UTF-8 compatible string' );        
    11.          }        
    12.           $count ++;        
    13.      }        
    14.       return   $count ;        
    15. }
相關文章
相關標籤/搜索