本文介紹了php中漢字編碼轉換的一些知識,分析了php編碼轉換的原理與方法,有需要的朋友參考下。
有關對mysql4.1字元集的理解,再講述如何php如何適應mysql的這種變化。 同樣適用於mysql5及以上的版本。 一.原理篇 mysql的字元集裡有兩個概念,一個是“character set(字元集)”,另一個是“collations”。 1. collations collations翻成中文是“校驗”,在網頁開發的過程中,這個詞彙,只在mysql裡使用,主要作用是指導mysql對字符的比較,比如, ascii字符集裡,collations規定了a小於b, a等於a,以及a是否等於a之類的。通常,大家基本上可以忽略collations的存在,因為每個字元集都有一個預設的collations,通常,使用預設的collations就可以了。 2.字符集 與此對比的是,字符集是個更廣的概念,即使是windows下普通的文本文件,也滲透到字符集的問題。不同的字符集,規定了不同的字符的編碼方式。一個character set (字元集)是一組符號和編碼,例如,ascii字元集,包括的字元有:數字,大小寫字母,分號、換行之類的符號,編碼方式是用一個7bit表示一個字元( a的編碼是65,b的編碼是98)。 ascii只規定了英文字母的編碼,非英文語言不能用ascii編碼表示,為此,不同的國家,都為自己的語言做了編碼,比如,我們國家,就有gb2312編碼。但每個國家之間的編碼不同,也存在著一些跨平台的問題,為此,一些國際化標準組織,就制定了一些國際通用的編碼,最常用的就是utf8了。 ascii只對英文符號和英文字母做了編碼,gb2312對英文符號,英文字母,漢字做了編碼,utf8對世界上所有的語言文字做了編碼,所以,gb1212的字符包含了ascii字符,utf8包含了gb2312字元。由此可見,utf8是所含最廣字符的字符集,所以,在一些多語言的web系統中,一般用utf8字符集(phpmyadmin使用utf8編碼)。 任何文本的存儲,都滲透到字符集的概念。包括資料庫,也包括普通的文字檔案。 主要術語: 字符:漢字,英文字母,標點符號,拉丁文等等。 編碼:將字元轉換成電腦儲存的格式,例如,a用65表示。 字符集:一組字符以及對應的編碼方式。 a. mysql的字元集 mysql目前支援多字元集,並且,支援在不同的字元集之間轉換(便於移植和支援多語言)。 mysql可以設定伺服器級字元集、資料庫級字元集、資料表級字元集、表列的字元集,實際上,最終使用字元集的地方是儲存字元的列,例如,你設定table1中col1列是字符型,col1才用到了字元集,如果table1表的col2列是int型,col2不使用字元集的概念。 伺服器級字元集、資料庫級字元集、資料表級字元集都是為列的字元集做預設選項的。 mysql一定有一個字元集,可以透過啟動時加參數指定,也可以編譯時指定,也可以在設定檔裡指定。 mysql伺服器字元集,只是做為資料庫層級的預設值。建立資料庫時,你可以指定字元集,如果沒指定,就使用伺服器的字元集。同理,建立表格時,你可以指定表格層級的字元集,如果沒指定,使用資料庫的字元集做為表格的字元集。建立列時,你可以指定某列的字元集,如果沒指定,就使用表格的字元集。 通常情況下,您只需設定伺服器級的字元集,其它的資料庫級,表級,以及列級的字元集,都繼承自伺服器級字元集。 由於utf8是最廣的字元集,所以,一般情況下,我們設定mysql伺服器級的字元集為utf8! b. 普通文本的字符集問題 任何文字的存儲,都存在著字元集的問題,普通文字檔案也不例外。 windows2000 的系統中,開啟記事本,「儲存為…」對話框,就有一個選項,可以讓你選擇儲存文字的編碼方式。 通常情況下,大家都會使用windows2000 的系統,都會使用預設的編碼,所以,不會碰到字元集的問題。 windows下,儲存文字檔案時,可以選擇編碼方式,但開啟文字檔案時,都是自動判斷編碼方式的。網路上有一個用windows2000 的記事本玩移動,聯通的笑話,大家可以搜搜,就是因為windows在打開文本文件時,編碼判斷錯誤引起的問題。 因為自動判斷編碼有時會錯誤,所以,有的文字文件,規定如何辨識自身所使用的編碼。 html檔案就是一個這樣的例子。 html是文字檔。儲存html檔案的時候,需要使用一個編碼,而且,在html檔案裡,也使用html語法,指定了該檔案所使用的編碼(例如)。如果html檔案沒有指定編碼,則瀏覽器會自動識別檔案的編碼。如果html指定了編碼,則瀏覽器使用html指定的編碼。 通常情況下,html檔案指定的charset和html檔案本身的編碼是一致的,但也有不一致的情況,如果不一致,就會導致網頁亂碼(此處亂碼,只和文字檔案有關,和資料庫無關。)使用專門的網頁編輯工具(如dreamwave),會自動根據網頁中的charset值來編碼檔案。 c. php mysql的字符集問題 php最終產生的是文本文件,但他要取資料庫裡的文本,或將文本存進資料庫。 由於mysql支援多字元集,預設情況下,mysql不知道php發給他的是什麼編碼的字符,所以,mysql要求客戶端(php)告訴他訪問的字元集是什麼。 php透過設定character_set_client,告訴mysql,php存進資料庫的是什麼編碼方式。 php透過設定character_set_results,告訴mysql,php需要取什麼樣編碼的資料。 php透過設定character_set_connection,告訴mysql,php查詢中的文本,使用什麼編碼。 mysql使用設定的編碼方式儲存文字。 假設mysql使用setserver來儲存文本,php的character_set_client是setclient,php的 character_set_results是setresult。那麼,mysql將php發送的文本,從setclient編碼方式,轉換成 setserver編碼方式,再存入資料庫,如果php取文本,mysql將文本從setserver轉換成setresult,再發送給php。 php檔案(最終產生的html檔案)本身有個編碼,如果mysql傳過來的編碼,與php檔案本身的編碼不同,那麼,整個網頁,必然亂碼。所以,php一般將自己的編碼方式,告訴mysql。 要確保不亂碼,就必須將三個編碼統一:一是網頁本身的編碼,二是html裡指定的編碼,三是php告訴mysql的編碼(包括character_set_client和character_set_results)。 第一和第二個編碼,如果使用dw之類的編輯器寫的網頁,通常是一致的,但用記事本寫的網頁,有可能不一致。 第三個編碼,需要手工通知mysql。這步驟可以透過在php裡使用mysql_query(“set names characterx”)來實現。 d.字符集的轉換問題 如果小字集轉換成大字元集,不會遺失數據,但大字集,轉換成小字集,可能會遺失資料。 例如,utf8裡有的字符,gb2312不一定有,所以,從utf8轉換到gb2312可能會遺失一些字符。 但有種情況例外,先從gb2312轉成utf8,再從utf8轉成gb2312,這種情況是不會丟失數據的,因為,剛開始轉換的文本,都是gb2312裡的字符,所以,整個過程都是gb2312的字元在轉換,不會遺失。 正因為utf8能容納世界上的所有字符,所以,資料庫一般使用utf8編碼。這使得,任何字元都可以存進utf8編碼的資料庫。 e. phpmyadmin亂碼的問題 phpmyadmin支援多國語言,這必定要求html頁面使用utf8編碼。 html頁面使用utf8編碼,這就必定要求phpmyadmin連接mysql時,character_set_client和character_set_results使用utf8編碼。 目前情況下,php連接mysql只能是使用set names(或其它幾個語句)來通知mysql的編碼方式,如果沒有明確的宣告編碼方式,都會使用latin1編碼。一般的程序,都沒有明確聲明 character_set_client變量,所以,都是將gb2312文本,按latin1編碼方式存在數據庫,phpmyadmin再用utf8格式讀取,肯定是亂碼的。 如果php程式以正確的編碼存入資料庫,肯定是沒有問題的。所以,需要修改的不是phpmyadmin.(雖然有時修改phpmyadmin可以解決亂碼問題,但這不是問題的根本) 二.總結篇 1.資料庫盡量使用utf8儲存(修改/etc/my.cnf,在[mysqld]段加上default-character-set=utf8) (已有的資料庫,先轉成utf8格式) 2.php程式在查詢資料庫之前,執行mysql_query(“set names xxxx”);其中xxxx是你網頁的編碼(charset=xxxx),如果網頁中charset=utf8,則xxxx=utf8,如果網頁中charset=gb2312 ,則xxxx=gb2312,如果網頁中的charset=ipaddr,則xxxx=ipaddr (開個玩笑,沒這編碼) 幾乎所有web程序,都有一段連接資料庫的公共程式碼,放在一個檔案裡,在這檔案裡,加入mysql_query(“set names”)就可以了。 3.phpmyadmin不需要做改動。 4.注意,為確保網頁實際編碼(windows保存對話框裡的編碼)和他聲明的編碼(charset=?)是一致的,請用dw之類的工具做網頁。 |