轉載:http://www.52net.com/html/2006/0428/63042.html
          作者:不祥


          PHP連接MySQL的過程中如果出現亂碼很多人會說,用"Set names '??'"就能解決問題,但很多時候還是會出現各種怪現象,比如說頁面能正常存取,但是phpmyadmin不能正常存取等現象。小弟經過驗證,產生了一些個人看法,歡迎大家討論和指正。

          MySQL數據庫操作過程中出現了三種字符集:
          1、頁面字符集(也就是 content="TEXT/HTML; CHARSET=GBK")
          2、連接字符集(也就是 "Set names 'GBK'")
          3、字段字符集(無論是庫還是表的字符集,將最終反映到字段上)
          一、實驗:
          1、情況一
          數據庫字段字符集:utf-8
          連接字符集:沒有顯式設置,默認為latin1
          頁面字符集:gbk

          存入過程:
          1)頁面用GBK表示的SQL向服務器提交存入請求;
          2)默認情況下(不用Set Names '??')服務器用latin1打開連接;
          3)服務器誤認為當前的SQL語句是用latin1表示的;
          4)服務器將GBK字符當作latin1字符,錯誤的運用“latin1轉UTF-8函數”將字符轉換后存入UTF-8字段中;
          5)( 錯誤的latin1(其實是GBK) => 錯誤的UTF-8)
          6)如果用phpmyadmin打開該表(用utf8連接)將會看到該字段為亂碼;

          讀取過程:
          1)默認情況下(不用Set Names '??')服務器用latin1打開連接;
          2)服務器將UTF-8字段中的值轉換為latin1返回給客戶端;
          3)(錯誤的UTF-8 => 錯誤的latin1(其實是GBK))該過程為存入過程5的逆過程。(剛好錯錯得對了)
          4)將服務器誤認為是latin1的GBK編碼按頁面字符集正常顯示;

          用示意圖來表示就是:

          CODE
          ? ?存入過程:
          ? ?----------------------
          ? ?頁面 ? ?連接 ? ? 存儲
          ? ?----------------------
          ? ?GBK => latin1 => utf-8
          ? ? ? ? ? ---------------
          ? ?------------- |
          ? ? ? ? ?| ? ? ? +------- 該過程得到的utf-8是一串不知所云的亂碼,但MySQL固執的認為這串碼為UTF-8
          ? ? ? ? ?|
          ? ? ? ? ?+------ MySQL將GBK誤認為是latin1

          ? ?讀取過程:
          ? ?----------------------
          ? ?頁面 ? ?連接 ? ? 存儲
          ? ?----------------------
          ? ?GBK <= latin1 <= utf-8
          ? ? ? ? ? ---------------
          ? ?------------- |
          ? ? ? ? ?| ? ? ? +------- 正是這串亂碼經過逆過程轉換回正確的GBK編碼,只是MySQL認為是latin1而已
          ? ? ? ? ?|
          ? ? ? ? ?+------ MySQL將誤認為是latin1的GBK編碼傳回了頁面,剛好得到正確的編碼。
          2、情況二
          數據庫字段字符集:utf-8
          連接字符集:gbk
          頁面字符集:gbk

          文字描述略。


          示意圖:

          CODE
          ? ?存入過程:
          ? ?----------------------
          ? ?頁面 ? 連接 ? 存儲
          ? ?----------------------
          ? ?GBK => GBK => utf-8
          ? ? ? ? ? ------------
          ? ?------------- |
          ? ? ? ? ?| ? ? ? +------- 該過程得到的utf-8是由GBK轉換而來的,是正確的utf-8編碼
          ? ? ? ? ?|
          ? ? ? ? ?+------ 頁面字符集等于連接字符集,MySQL認為頁面傳遞給它的是GBK編碼,它的想法正好符合事實。


          ? ?讀取過程:
          ? ?----------------------
          ? ?頁面 ? 連接 ? 存儲
          ? ?----------------------
          ? ?GBK <= GBK <= utf-8
          ? ? ? ? ? ? ? ---------------
          ? ?------------- |
          ? ? ? ? ?| ? ? ? +------- 用“utf-8轉GBK函數”將正確的utf-8編碼轉換回GBK
          ? ? ? ? ?|
          ? ? ? ? ?+------ 頁面字符集等于連接字符集,顯示沒有任何問題。

          3、情況三
          數據庫字段字符集:gbk
          連接字符集:沒有顯式設置,默認為latin1
          頁面字符集:gbk

          CODE
          ? ?存入過程:
          ? ?----------------------
          ? ?頁面 ? 連接 ? 存儲
          ? ?----------------------
          ? ?GBK => latin1 => GBK
          ? ? ? ? ? ------------
          ? ?------------- |
          ? ? ? ? ?| ? ? ? +------- 字符被“latin1轉GBK函數”轉換的成了亂碼,但MySQL認為它是GBK,所以工具無法正常顯示。
          ? ? ? ? ?|
          ? ? ? ? ?+------ MySQL認為頁面傳遞給它的是latin1編碼,它將在后續過程中畫蛇添足地將正確的GBK轉換為亂碼。


          ? ?讀取過程:
          ? ?----------------------
          ? ?頁面 ? 連接 ? 存儲
          ? ?----------------------
          ? ?GBK <= latin1 <= GBK
          ? ? ? ? ? ---------------
          ? ?------------- |
          ? ? ? ? ?| ? ? ? +------- “GBK轉latin1函數”將亂碼轉換為GBK,但MySQL卻認為它們是latin1
          ? ? ? ? ?|
          ? ? ? ? ?+------ 錯誤的latin1編碼其實是正確的GBK編碼,頁面顯示正常,但工具顯示不正常。


          二、字符集之間的轉換
          筆者試著將GBK字符誤當作latin1轉換為錯誤的utf-8能成功,逆過程中將亂碼轉換回latin1得到的剛好是正確的GBK

          CODE
          ? ?$str = "中文測試";
          ? ?$str_tran = iconv('latin1', 'utf-8', $str);
          ? ?echo $str_tran; // 顯示亂碼,既不是GBK也不是utf-8和latin1


          ? ?echo "<br>-----------<br>";


          ? ?$str_re_tran = iconv('utf-8', 'latin1', $str_tran);
          ? ?echo $str_re_tran; ?// 顯示 “中文測試”


          而將GBK字符誤當作utf-8轉換為錯誤的GBK編碼則出現錯誤
          CODE
          ? ?$str = "中文測試";
          ? ?#$str_tran = iconv('utf-8', 'gbk', $str); ? ?// 錯誤?。?!


          可見一種編碼是否能被當作另一種編碼被轉換為第三種編碼,取決于編碼的固有屬性,上面我們舉的第一個例子只是碰巧GBK編碼能被誤當作latin1被轉換為utf-8。如果是如下情況,則數據庫肯定不能正常存取數據。
          GBK => utf-8 => GBK(未實驗)
          三、結論
          頁面能正常存取但phpmyadmin不能正常存取,從嚴格意義上來說應該是一種錯誤,頁面是否能正常存取取決于連接字符集是否能正常的被轉換為存儲字符集。
          要保證頁面能正常存取,并且工具也能正常使用,一般保持頁面字符集等于或兼容連接字符集就可以了。
          posted on 2006-12-10 05:08 jackstudio 閱讀(894) 評論(0)  編輯  收藏 所屬分類: commonphp
          主站蜘蛛池模板: 福贡县| 闵行区| 龙泉市| 文昌市| 秦皇岛市| 石城县| 永城市| 潞西市| 拉萨市| 伊宁市| 子洲县| 绥宁县| 赤峰市| 工布江达县| 县级市| 潜江市| 灌云县| 日喀则市| 望奎县| 荆门市| 南通市| 边坝县| 枞阳县| 陕西省| 沭阳县| 福鼎市| 延长县| 两当县| 灌云县| 宁化县| 北流市| 和龙市| 婺源县| 蒙城县| 民权县| 绥化市| 青岛市| 河间市| 正安县| 山东省| 阳高县|