轉(zhuǎn)載:http://www.52net.com/html/2006/0428/63042.html 作者:不祥
PHP連接MySQL的過程中如果出現(xiàn)亂碼很多人會說,用"Set names '??'"就能解決問題,但很多時候還是會出現(xiàn)各種怪現(xiàn)象,比如說頁面能正常存取,但是phpmyadmin不能正常存取等現(xiàn)象。小弟經(jīng)過驗(yàn)證,產(chǎn)生了一些個人看法,歡迎大家討論和指正。
MySQL數(shù)據(jù)庫操作過程中出現(xiàn)了三種字符集: 1、頁面字符集(也就是 content="TEXT/HTML; CHARSET=GBK") 2、連接字符集(也就是 "Set names 'GBK'") 3、字段字符集(無論是庫還是表的字符集,將最終反映到字段上) 一、實(shí)驗(yàn): 1、情況一 數(shù)據(jù)庫字段字符集:utf-8 連接字符集:沒有顯式設(shè)置,默認(rèn)為latin1 頁面字符集:gbk
存入過程: 1)頁面用GBK表示的SQL向服務(wù)器提交存入請求; 2)默認(rèn)情況下(不用Set Names '??')服務(wù)器用latin1打開連接; 3)服務(wù)器誤認(rèn)為當(dāng)前的SQL語句是用latin1表示的; 4)服務(wù)器將GBK字符當(dāng)作latin1字符,錯誤的運(yùn)用“l(fā)atin1轉(zhuǎn)UTF-8函數(shù)”將字符轉(zhuǎn)換后存入UTF-8字段中; 5)( 錯誤的latin1(其實(shí)是GBK) => 錯誤的UTF-8) 6)如果用phpmyadmin打開該表(用utf8連接)將會看到該字段為亂碼;
讀取過程: 1)默認(rèn)情況下(不用Set Names '??')服務(wù)器用latin1打開連接; 2)服務(wù)器將UTF-8字段中的值轉(zhuǎn)換為latin1返回給客戶端; 3)(錯誤的UTF-8 => 錯誤的latin1(其實(shí)是GBK))該過程為存入過程5的逆過程。(剛好錯錯得對了) 4)將服務(wù)器誤認(rèn)為是latin1的GBK編碼按頁面字符集正常顯示;
用示意圖來表示就是:
CODE | ? ?存入過程: ? ?---------------------- ? ?頁面 ? ?連接 ? ? 存儲 ? ?---------------------- ? ?GBK => latin1 => utf-8 ? ? ? ? ? --------------- ? ?------------- | ? ? ? ? ?| ? ? ? +------- 該過程得到的utf-8是一串不知所云的亂碼,但MySQL固執(zhí)的認(rèn)為這串碼為UTF-8 ? ? ? ? ?| ? ? ? ? ?+------ MySQL將GBK誤認(rèn)為是latin1
? ?讀取過程: ? ?---------------------- ? ?頁面 ? ?連接 ? ? 存儲 ? ?---------------------- ? ?GBK <= latin1 <= utf-8 ? ? ? ? ? --------------- ? ?------------- | ? ? ? ? ?| ? ? ? +------- 正是這串亂碼經(jīng)過逆過程轉(zhuǎn)換回正確的GBK編碼,只是MySQL認(rèn)為是latin1而已 ? ? ? ? ?| ? ? ? ? ?+------ MySQL將誤認(rèn)為是latin1的GBK編碼傳回了頁面,剛好得到正確的編碼。 | 2、情況二 數(shù)據(jù)庫字段字符集:utf-8 連接字符集:gbk 頁面字符集:gbk
文字描述略。
示意圖:
CODE | ? ?存入過程: ? ?---------------------- ? ?頁面 ? 連接 ? 存儲 ? ?---------------------- ? ?GBK => GBK => utf-8 ? ? ? ? ? ------------ ? ?------------- | ? ? ? ? ?| ? ? ? +------- 該過程得到的utf-8是由GBK轉(zhuǎn)換而來的,是正確的utf-8編碼 ? ? ? ? ?| ? ? ? ? ?+------ 頁面字符集等于連接字符集,MySQL認(rèn)為頁面?zhèn)鬟f給它的是GBK編碼,它的想法正好符合事實(shí)。
? ?讀取過程: ? ?---------------------- ? ?頁面 ? 連接 ? 存儲 ? ?---------------------- ? ?GBK <= GBK <= utf-8 ? ? ? ? ? ? ? --------------- ? ?------------- | ? ? ? ? ?| ? ? ? +------- 用“utf-8轉(zhuǎn)GBK函數(shù)”將正確的utf-8編碼轉(zhuǎn)換回GBK ? ? ? ? ?| ? ? ? ? ?+------ 頁面字符集等于連接字符集,顯示沒有任何問題。 |
3、情況三 數(shù)據(jù)庫字段字符集:gbk 連接字符集:沒有顯式設(shè)置,默認(rèn)為latin1 頁面字符集:gbk
CODE | ? ?存入過程: ? ?---------------------- ? ?頁面 ? 連接 ? 存儲 ? ?---------------------- ? ?GBK => latin1 => GBK ? ? ? ? ? ------------ ? ?------------- | ? ? ? ? ?| ? ? ? +------- 字符被“l(fā)atin1轉(zhuǎn)GBK函數(shù)”轉(zhuǎn)換的成了亂碼,但MySQL認(rèn)為它是GBK,所以工具無法正常顯示。 ? ? ? ? ?| ? ? ? ? ?+------ MySQL認(rèn)為頁面?zhèn)鬟f給它的是latin1編碼,它將在后續(xù)過程中畫蛇添足地將正確的GBK轉(zhuǎn)換為亂碼。
? ?讀取過程: ? ?---------------------- ? ?頁面 ? 連接 ? 存儲 ? ?---------------------- ? ?GBK <= latin1 <= GBK ? ? ? ? ? --------------- ? ?------------- | ? ? ? ? ?| ? ? ? +------- “GBK轉(zhuǎn)latin1函數(shù)”將亂碼轉(zhuǎn)換為GBK,但MySQL卻認(rèn)為它們是latin1 ? ? ? ? ?| ? ? ? ? ?+------ 錯誤的latin1編碼其實(shí)是正確的GBK編碼,頁面顯示正常,但工具顯示不正常。 |
二、字符集之間的轉(zhuǎn)換 筆者試著將GBK字符誤當(dāng)作latin1轉(zhuǎn)換為錯誤的utf-8能成功,逆過程中將亂碼轉(zhuǎn)換回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字符誤當(dāng)作utf-8轉(zhuǎn)換為錯誤的GBK編碼則出現(xiàn)錯誤
CODE | ? ?$str = "中文測試"; ? ?#$str_tran = iconv('utf-8', 'gbk', $str); ? ?// 錯誤!!! |
可見一種編碼是否能被當(dāng)作另一種編碼被轉(zhuǎn)換為第三種編碼,取決于編碼的固有屬性,上面我們舉的第一個例子只是碰巧GBK編碼能被誤當(dāng)作latin1被轉(zhuǎn)換為utf-8。如果是如下情況,則數(shù)據(jù)庫肯定不能正常存取數(shù)據(jù)。 GBK => utf-8 => GBK(未實(shí)驗(yàn)) 三、結(jié)論 頁面能正常存取但phpmyadmin不能正常存取,從嚴(yán)格意義上來說應(yīng)該是一種錯誤,頁面是否能正常存取取決于連接字符集是否能正常的被轉(zhuǎn)換為存儲字符集。 要保證頁面能正常存取,并且工具也能正常使用,一般保持頁面字符集等于或兼容連接字符集就可以了。 |
posted on 2006-12-10 05:08
jackstudio 閱讀(893)
評論(0) 編輯 收藏 所屬分類:
common 、
php