一、遇到的問題

曾經被字符集間複雜的轉換搞怕了,正好新項目要求國際化,需要能夠顯示多種語言,於是一開始就規定統統使用 UTF-8 編碼。

  1. 所有代碼文件使用 UTF-8 編碼存盤
  2. MySQL數據庫所有表,所有字段設置 Collation (中文翻譯為“整理”?)屬性為 “utf8_general_ci”
  3. 所有頁面輸出
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>

即便是這樣,PHP 從數據庫中讀取內容,顯示到網頁上,還是出現了亂碼,英文沒問題,中文統統都是?問號。這樣也行?艱苦卓絕的 debug 開始了……

開始debug

二、調查原因

MySQL 的字符集以繁多而著名,而其默認又是 latin1 的瑞典語編碼,數據導入導出的時候一不留神就亂碼了。

參考以上鏈接的官方文檔,總結之:MySQL 對於字符集的支持細化到四個層次:

  1. server 服務器級
  2. database 數據庫級
  3. table 表級
  4. connection 連接級

確保每一個級別都是使用的 UTF-8 編碼。檢查了一下,貌似我沒有設置 connection 連接級。前三種字符集級別只是規定了數據存儲在 MySQL 中的編碼格式,客戶端讀出數據後完全可以按照自己的意願來解讀數據。最後的 connection 連接級就是規定了客戶端以什麼編碼來解析讀取到的數據。也就是說,不論是 php 代碼還是 DB 管理軟件,在從 MySQL 讀取數據之前都需要設定自己作為客戶端的編碼格式。

思考中

好吧,那麼,在任何查詢執行之前,先執行一句 set names utf-8。(使用框架進行開發的話,大多數框架應該會自動完成這一步,程序員一般只需要改配置文件)

$conn = mysql_connect($db_host, $db_user, $db_password);
if(!$conn)
    die("Could not connect to mysql.");
mysql_select_db($db_name);
mysql_query("set names 'utf-8'");

刷新頁面,仍舊亂碼。

淚流滿面

三、解決

只好再繼續調查。¥#$…&%=^*&+%-#!@_@ 苦逼地一天就這樣過去了……

咦,等等,官方文檔里寫的是 set names utf8 哦,和 set names utf-8 有啥區別么?趕緊試一下。

刷新頁面,我擦,正常了。

WTF!!

搜了一下,發現被坑的人還真不少。UTF-8應該是標準的寫法,在大多數場合都是有中間那個橫杠的,只是MySQL這裡偏偏就非主流去掉了橫杠使用UTF8。

遇到同樣問題,而本文未能幫你解決的,這篇亂碼總結可能會幫到你。