朱海巖
(呂梁學院汾陽師范分校,山西 汾陽 032200)
PHP與MySQL Web應用平臺中文亂碼問題研究
朱海巖
(呂梁學院汾陽師范分校,山西 汾陽 032200)
在運用PHP和MySQL平臺進行Web應用程序開發時,經常會在處理中文信息過程中出現亂碼.本文就亂碼產生的原因進行了深入地分析和討論,并提出了徹底解決亂碼問題的方法.
亂碼;字符集;MySQL
PHP和MySQL以其開源、免費、高性能等眾多優勢,在Web應用領域占領了越來越多的市場份額.現在,PHP與MySQL的主流版本已經能夠完全兼容中文信息,但是在進行中文應用程序開發的過程中會經常出現一些亂碼問題.究其原因,是因為計算機中漢字的編碼方式不統一.同一個漢字在不同字符集中的編碼是不一樣的,如果一些應用程序默認采用了不同的字符集又缺乏合理的轉換機制,在相互通信中就極有可能出現中文亂碼.
GB2312-80也稱GB2312是漢字字符集和編碼的代號,是最基本的漢字編碼集.中文全稱為“信息交換用漢字編碼字符集”,1980年,由中華人民共和國國家標準總局發布,1981年5月1日起實施.
GB2312字符集只收錄簡化漢字,以及常用字母和符號,共收錄有7445個字符,其中簡化漢字6763個,字母和符號682個.在大陸及海外使用簡體中文的地區(如新加坡等)是使用最廣泛的中文編碼.該標準的制定和應用為規范、推動中文信息化進程起了很大作用,其最大的特點是只支持簡體中文.
GBK全名為“漢字內碼擴展規范”,即GB2312-80的擴展字符集.
1993年,Unicode 1.1版本推出,收錄了中國大陸、臺灣、日本及韓國通用字符集的漢字,總共有20,902個.隨后,中國大陸訂定了等同于Unicode 1.1版本的GB 13000.1-93.
由于GB 2312-80只收錄了6763個漢字,有不少簡體漢字以及臺灣和香港地區使用的繁體字,日語及朝鮮語漢字等,并未有收錄在內.于是,一些軟件開發商利用了GB 2312-80未使用的編碼空間,收錄了所有出現在Unicode 1.1及GB 13000.1-93之中的漢字,制定了GBK編碼.雖然GBK收錄了所有Unicode 1.1及GB 13000.1-93之中的漢字,但是編碼方式與Unicode 1.1及GB 13000.1-93不同.
UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,也是一種前綴碼.它可以用來表示Unicode標準中的任何字符,且其編碼中的第一個字節仍與ASCII兼容,這使得原來處理ASCII字符的軟件無須或只須做少部份修改,即可繼續使用.因此,它逐漸成為電子郵件、網頁及其他存儲或傳送文字的應用中,優先采用的編碼.
總之,以上幾種字符集都能支持中文,但又有所不同.GB2312-80只能支持中文簡體,GBK是GB2312-80的超集,支持中文簡體、繁體以及日文、韓文符號.UTF-8是一種更通用的字符集,支持世界各種語言的符號.如果某個Web應用程序只是針對國內用戶,可以考慮采用GB2312-80字符集,GBK是一種非官方標準的字符集,有時還是會有些問題.如果考慮到該Web應用有可能面對國際用戶或者是為了取得更好的兼容性,則應該使用UTF-8字符集.
● character_set_server:服務器字符集,用來為create database命令提供默認值.
● character_set_database:當前數據庫的字符集,為create table命令提供默認值.
● character_set_table:當前數據表的字符集,為列的字符集提供默認值.
● character_set_client:客戶端默認字符集,當服務器接收到客戶端發來的數據時,按些字符集進行解碼.
● character_set_results:結果字符集,當服務器向客戶端返回查詢結果時,以此字符集規則進行編碼.
● character_set_connection:連接字符集,這個變量用來決定MySQL怎么處理客戶端發來的SQL命令.MySQL會把SQL命令從character_set_client編碼轉到character_set_connection編碼,然后再執行.
假設客戶端(即為PHP頁面端)采用UTF-8字符集.
1>客戶端向服務器端(即MySQL)發送數據,這些數據根據假設以UTF-8字符集編碼.
2>服務器端收到客戶端發來的數據,以character_set_client(假設其值為latin1)規定的編碼方式進行解碼.
3>服務器端處理完客戶端的查詢請求,準備好數據,以character_set_result(假設其值為latin1)形式編碼并發送到客戶端.
4>客戶端接收到服務器端發來的數據,并以自己的編碼形式(第1>步假定為UTF-8)進行解碼.
第1>步向服務器發送了一組UTF-8編碼的數據,但服務器端以latin1字符集規則進行解碼,則不能還原數據,所以存儲到數據庫中的內容會顯示成亂碼.
第4>步服務器端向客戶端發送了latin1編碼形式的數據,但客戶端以UTF-8形式解碼,則顯示在頁面上的內容也是亂碼.
客戶端向服務器端發送正確命令而服務器端不能正確識別也是由于類似原因.
綜上所述,產生亂碼問題的原因可以總結如表1:

表1
所以,將服務器端的character_set_client、character_set_connection、character_set_results三個系統變量的值設置為客戶端所采用的字符集,則可以從根本上解決中文亂碼問題.
一般情況下,html的head部分會有如下代碼:
此行代碼指定了本頁面的字符使用UTF-8字符集編碼.
如果是純PHP文件,不包含html代碼,也可以使用以下代碼指定該頁面的字符集:
header(“content-type:text/html;charset=utf-8”);
以上兩處代碼中的utf-8可以修改成任意合法的字符集.
1>修改MySQL配置文件
在MySQL的安裝目錄下找到其配置文件my.ini,分別在 [mysqld]與 [mysql]下添加代碼”default-character-set=utf8”.
保存my.ini并重新啟動MySQL服務,會發現系統變量的值均被改為utf8.
2>在客戶端動態改變MySQL系統變量
由于大多數的用戶只是租用虛擬主機運營網站,因此根本無權修改MySQL的配置文件.而且一般情況下程序員也不知道將來代碼會放到什么樣的服務器環境下運行,因此在客戶端與服務器端建立連接以后,動態修改服務器端相關系統變量的值,是一種更通用和可靠的辦法.具體代碼如下:

PHP與MySQL Web應用平臺下產生中文亂碼的根本原因在于字符集編碼方式的不統一.只要約定采用統一的字符集或者控制不同字符集之間正確轉換,則可以從根本上解決該平臺下的中文亂碼問題.
〔1〕Luke Welling、Laura Thomson, 武欣譯.PHP 和MySQL Web開發[M].北京:機械工業出版社,2009.
〔2〕姜承堯.MySQL技術內幕:InnoDB存儲引擎[M].北京:機械工業出版社,2011.
〔3〕Charles A.Bell,楊濤、王建橋、楊曉云等譯.深入理解MySQL[M].北京:人民郵電出版社,2010.
〔4〕W.Jason Gilmori,朱濤江譯.PHP 與 MySQL 程序設計[M].北京:人民郵電出版社,2007.
TP391.1
A
1673-260X(2011)08-0036-02