網頁設計分享-MySQL和phpMyAdmin中文亂碼

網頁設計教學分享-MySQL和phpMyAdmin工中文亂碼

最近筆者勤於備份資料,而且試著把建立在MySQL資料庫中的資料在各種平台轉來轉去,發現了許多的問題,而這些問題在網路上有許多網友問過,但看到很多人找不出答案,因而放棄重裝系統或者放棄掉寶貴的舊有資料,那麼我相信筆者這一篇文章可能會讓您放棄掉堅持在所謂的”UTF-8中文亂碼”的迷思。
為什麼筆者稱之為”迷思”,許多使用PHP程式語言搭配MySQL資料庫的朋友百分之一百零一會使用phpMyAdmin,但隨著MySQL資料庫版本的升級,phpMyAdmin資料庫管理工具也跟著改版,曾幾何時您會發現,原本使用phpMyAdmin工具可以在資料表中看到的中文,變成了亂碼。

狀況(1) phpMyAdmin未升級前正常,升級後中文變亂碼
測試環境
phpMyAdmin版本:2.5.6
MySQL版本:4.1.8-nt
架站環境:Appserv – Win32
網站的預設編碼:big5
儲存於MySQL的編碼:latin1

 

phpMyAdmin版本:2.6.1 rc-1
MySQL版本:4.1.8-nt
架站環境:Appserv – Win32
網站的預設編碼:big5
儲存於MySQL的編碼:latin1

 

phpMyAdmin工具版本升級後,結果中文變成亂碼。

這種情況並不會影響前台輸出中文,所以訪客瀏覽網頁時一樣正常,差別在於自己在phpMyAdmin時工作並不方便,中文都變成了亂碼的原因在於瀏覽器預設的檢視編碼不同,原本舊版的2.5.6版以預射big5繁體中文去檢視網頁,而這個版本以後的新版phpMyAdmin一律都以UTF-8檢視,因此才會變成亂碼。

 

這並不會影響到原本儲存於資料庫中的資料,所以大可不用擔心,解決的方法就是使用舊版的phpMyAdmin或者自己寫一套資料庫管理工具、另外找尋非UTF-8檢視的資料庫管理軟體。

狀況(2) 中文UTF-8編碼網站,前台瀏覽正常,phpMyAdmin檢視中文變成亂碼
測試環境
phpMyAdmin版本:2.6.1 rc-1
MySQL版本:4.1.8-nt
架站環境:Appserv – Win32
網站的預設編碼:UTF-8
儲存於MySQL的編碼:UTF-8

也許很多朋友和筆者和MySQL中文亂碼奮戰的時候,會看過很多”品種”的中文亂碼,為什麼phpMyAdmin已經是用UTF-8檢視網頁了,看到的結果仍舊是火星文,後來經過反覆的測試,筆者先規納出以下的圖表作說明:

 

一般而言,初次安裝Appserv架站軟體或者在Linux系統中建立MySQL資料庫,預設的資料庫編碼及資料傳送方式都會是latin1,從一個不是UTF-8的網頁表單中鍵入資料,送出到處理的php程式,它取得的字串就不會是UTF-8編碼,而以latin1的編碼儲存到資料表欄位中,最終的編碼也是latin1。所以只要用舊版的phpMyAdmin去瀏覽,看到的一樣會是正常的中文字。

而UTF-8網站的處理過程如下圖:

 

在UTF-8網頁中的表單輸入資料,其資料在UTF-8網頁中可以檢視,因為當輸入的時候該資料本身就是UTF-8編碼的資料,當送出表單時,這些UTF-8的資料會經過資料庫的處理存入欄位中,因為MySQL資料庫預設傳送的編碼是latin1,所以它把UTF-8編碼資料以latin1編碼存入資料表的欄位中,而變成亂碼。但這個亂碼仍然是UTF-8編碼的,只是因為被latin1給弄亂了,所以不管是用什麼樣的編碼語系去讀取這些字串,看到的只是亂碼,不可能讀的出正常的中文字串。

當前台的程式呼叫時(例如phpbb論壇),MySQL資料庫會以latin1將這些亂碼”還原”成”正常”的UTF-8中文字。

在latin1的預設編碼下,不管怎麼在phpMyAdmin更改資料庫、資料表、資料表欄位的連線校對為utf8_general_ci、utf8_unicode_ci或latin1_swedish_ci等編碼,都會是一樣的結果,看到的都會是同一款品種的火星文。

如果您想要在phpMyAdmin中看到UTF-8顯示正常的中文字,以下有兩種解決方案:

更改MySQL預設的連線編碼設定
Linux或Unix-like環境
找出 /etc/my.cnf 檔案,這個檔案是MySQL資料庫的設定檔,詳細的說明請參閱vbird的WWW伺服器#MySQL效能調校,內文有更詳細的參數說明,但在此很簡單地只要改兩個地方就可以讓MySQL預設的latin1編碼連線方式改成UTF-8。

 

Win32 – Appserv架站軟體
在Windows環境下,則MySQL設定檔為my.ini,一般而言存放在c:/window 這個目錄底下,同樣地找尋上述兩個地方將其從latin1改成utf8。

程式語法限定MySQL傳送的編碼
在此以phpBB2論壇為例,在db.php中第60行以後加入以下指令,告知MySQL都以UTF-8的方式傳送資料:

 

筆者將一個UTF-8網站,但MySQL是預設latin1連線的網站,在讀取資料庫的程式碼中,加入如上圖示第62行的程式碼之後,網頁上只要是從資料庫讀出來的中文字都變成了亂碼,但試著新增一筆資料,結果如下:

 

宣告以UTF-8編碼連線後,原本好好的UTF-8中文都變成亂碼了,因為那些資料原本都是以latin1重編過的UTF8資料,要以latin1編碼呼叫才能夠還原出原本的UTF-8中文字,但現在強制以UTF-8編碼連線,就無法還原了,因此,讀者們看到的火星文和資料庫中的一模一樣地出現在網頁上。

 

宣告以UTF-8編碼連線後,所輸入的中文字,終於可以在phpMyAdmin中看到,這可是確確實實的UTF-8中文,而不是被latin1編碼搞亂的中文字。但是看看上圖藍色框框的部份,不同品種的火星文出現了!但是那些中文字都變成了一堆??????????????問號,這是為什麼呢?看看下圖,筆者相信讀者們的觀念就釐清了。

 

因為在筆者的測試中,只有把第二個欄位的連線效對改成UTF-8,其它都一樣還是維持latin1的連線效對,也就是說,如果全部以UTF-8編碼的方式,確實地在phpMyAdmin等以UTF-8檢視的資料庫管理軟體中看到非亂碼的中文字,不但MySQL的連線部份要UTF-8編碼,資料表的欄位也必須用UTF-8的連線較對,否則會失敗。

 狀況(3) 中文UTF-8編碼網站,在其它Hosting使用mysqldump指令備份,mysql指令匯入正常,但在MySQL 4.x部份中文錯亂或匯入失敗
相信一定會有讀者遇到這種情況,由其是在外國租用Hosting空間或VPS的讀者,因為外租的主機是不可能為單一個戶去改變系統的預設值的,尤其在英語系國家,存在任何字碼,英文字還是英文字,並不會因為說存在不同的編碼就變成亂碼,所以一律都是預設的。因此,在沒辦法去要求主機商將MySQL的連線編碼改成big5或UTF-8的情況下,一切都只能靠自己解決了。

用mysqldump指令備份資料庫是最完整的方法,而且不需要將主機服務停止就可以隨時備份,但注意,如果您是採取完美顯示UTF-8中文字的解決方案,在沒辦法使用UTF-8編碼連線的狀況下,在國外預設為latin1的主機下使用mysql指令匯入資料庫會失敗!

即使自己的主機預設是latin1,國外的主機預設也是latin1,照理說用mysqldump指令備份,mysql指令還原,會非常順利,但筆者在測試的過程中發現,某些情況下,部份UTF-8中文字正常,但部份中文字會跳字(變成其它字)和變成亂碼,後來筆者發現,這是因為Mysql資料庫版本不同而發生的,當筆者在MySQL版本4.1.8(預設連線編碼latin1)的情況下使用mysqldump備份,傳到國外主機,MySQL版本為5(預設連線編碼latin1),用mysql指令匯入,非常地順利,一下子網站就可以正常運行了,中文字也正常地顯示在網頁上。

但當筆者要備份國外主機的資料庫回自己的主機時,卻發現匯入時指令中斷,打開備份檔將有問題的SQL字句都刪除後,再匯入,雖然順利匯入到資料庫中了,但中文字卻出現跳字和部份亂碼的情況,筆者研判是,版本相容性的問題,舊版本的備份檔可以匯進新版本的MySQL資料庫,但從最新版本的資料庫備份出的檔案要匯進舊版本可能就會發生問題了。

最後筆者將自己測試用的主機MySQL的版本也從4.1.8升級到5系列版本,在國外主機備份的檔案,一下子就順利匯入了,也不再有中文字跳字及部份亂碼的情況發生。

附錄
MySQL資料庫備份語法
如果您是使用Appserv架站軟體,那麼先從開始列 – 執行 – 輸入: cmd

 

接下來會出現以下視窗,對於不熟DOS介面的讀者跟著輸入指令就可以了。

 

指令是:

mysqldump – -opt database > backup-file.sql

其中- -opt (這是兩個-連在一起,因為本網站程式會將連在一起的減號取代字串) 是快速完整備份的指令,紅色字的database是您要備份的資料庫名稱,綠色字的 backup-file.sql是匯出而產生的備份檔,可自由命名。在Linux也是用這個語法。

MySQL資料庫匯入備份檔語法
指令是:

mysql database < backup-file.sql
 
後記
希望這篇教學文章可以省掉讀者們不少時間,筆者花了許多時間在和這些中文亂碼搏鬥,只求一個安心的備份方式,後來有些心得,仍覺得在網路上還沒有一篇文章比較詳細具體的說明相關的狀況,所以筆者花了約6個小時準備這篇文章,如果可以省下一位讀者10個小時的摸索和試誤,1000個讀者就為這個地球省下10000個小時的時間了, 而筆者需要的是您花30秒迴響給我的鼓勵與支持,謝謝,希望對您有幫助。

《轉貼處》
AdSenseor網路觀察家
網址:http://www.adsenseor.com

網頁設計大膽狂塗網頁設計教學分享

留下迴響

你必須 登入 才可回覆