前言:
說實話,
涼鞋也覺得UTF8 是好東西…
畢竟同畫面顯示中日韓對東亞人的吸引力是不小的…
(當然好處不只是這點啦…)
不僅是網頁程式…
很多應用程式的核心都開始使用Unicode 編碼…
目的是顯而易見的:支援多語言顯示…
微軟的所有軟體都是Unicode 核心…
所以日文軟體拿到你的中文XP 上是可以正常顯示的…
而中文98 就會因為GB 核心安裝其他語言軟體時造成亂碼…
至於UTF8 ,
可以說是Unicode 的一個分支,
它用三個位元組保存一個漢字…
(Unicode 用四個位元組)
應用軟體都集體投奔Unicode 了…
就不允許我們搞網頁程式的用UTF8?
本文中涼鞋就盡量多方位介紹UTF8 編碼下的PHP 程式設計…
至於為什麼要單獨介紹「中文」…
一來是因為英文這玩意實在不需要考慮UTF8 …
除非你準備好做多語言系統…
(我要發些牢騷:現在的老外寫程式時根本不重視這個問題…)
二來是中日韓等多字節語系在UTF8 編碼下的處理方式其實大同小異…
依葫蘆畫瓢即可…
好…先從資料庫處理部分開始吧…
==========================================
連接資料庫
很多人剛升級到Mysql 4.1 時會發現資料亂掉了…
其實是因為Mysql 從4.1 開始支援字元集了…
而且預設字符集正是UTF8 …
(充分證明與國際接軌的重要性… 嘿嘿…)
而以前我們大多使用utf8 或是GBK 編碼…
這樣以來輸出的資料當然是亂碼…
要解決亂碼…
就得讓程式知道該取得什麼編碼的資料…
我們假設你以前的資料庫是utf8 編碼的…
那你可以在查詢前面加上一句
mysql_query('SET CHARACTER SET utf8') or die("Query failed : " . mysql_error());
當然,由於4.1 以上才需要這樣處理,
因此我們可以加上判斷:
$mysqlversion = $db->query_first("SELECT VERSION() AS version");
if ($mysqlversion['version'] >= '4.1')
{
mysql_query('SET CHARACTER SET utf8') or die("Query failed : " . mysql_error());
}
這樣以來不管Mysql 預設編碼是什麼都可以正常存取了…
(不論您是存活期,還是存定期,甚至是零存整取都沒有問題鳥…)
但是,人家都國際化鳥…
您還在用utf8 行麼?
如何轉碼呢?
還有…
資料升級時出現亂碼怎麼辦?
涼拌!
且聽下回分解…
============================================= =
資料升級至4.1
要升級…
就得先導出…
要說老外還真不負責…
以前的導出方式總是弄丟一些中文字元…
例如把「我愛你娘」弄成「我愛你」啦…
(通常是遺失一段資料最末尾的字)
整個兒差了一輩子…
(用石榴姐的話說就是「這麼大逆不道的事實在是太刺激了」…)
為了保護您脆弱的心臟…
也為了維護中國傳統倫理道義…
您可以把資料包含中文字元的欄位改為二進位(Binary)編碼…
具體方法嘛…
可以執行這個語句:
ALTER TABLE `表名` CONVERT TO CHARACTER SET binary;
這樣,那些字元類型字段,如:
CHAR、VARCHAR 和TEXT
將轉換為
BINARY、VARBINARY 和BLOB
然後再匯出並匯入到4.1 環境中…
當然,最後一項繁瑣的工作是:
你需要把它們的類型再改回來…
有往4.1 升級的…
當然也有往下降級的…
怎麼降級? ? ?
涼鞋去上廁所…
而您請翻下頁…
============================================ ===
資料從4.1 降級
有人發現從4.1匯出的SQL 檔案無法匯入低版程式…
問題其實很簡單…
而且Mysql 已經為我們想好了一切…
導出時請加入–compatible 參數…
我們假設您的資料庫是utf8 編碼的…
而且目標資料庫版本為4.0 …
那麼命令列下這麼寫:
shell>mysqldump --user=username --password=password --compatible=mysql40 --default-character-set=utf8 database > db.sql
這樣匯出的SQL 檔案就能夠順利匯入低版資料庫了…
資料庫部分算是搞定了…
但PHP 程式設計方面要如何注意呢?
還得勞您翻下頁…
http://www.knowsky.com
=============================================
PHP 檔案編碼
是否所有PHP 檔案都必須轉換成UTF8 編碼呢?
涼鞋告訴您是NO ……
這麼說吧……
如果文件中包含需要顯示出來的中文字元…
就應該轉為UTF8 編碼…
舉例:
// 我是涼鞋
echo time();
上面的程式碼雖有程式碼…
但由於存在於註釋中…
不會輸出…
所以這個頁面可以不用轉換為UTF8 格式…
再如:
echo "我是涼鞋";
這個明顯有中文字元輸出…
您還是老實轉換為UTF8 吧…
當然現在很多程式都採用模板(語言包)技術…
程式(非語言包檔案)裡是看不到任何供輸出的字元的…
這樣以來我們只需要將語言包檔案轉成UTF8 編碼即可…
(語言包的優勢就在這裡啊…… 啊哈哈哈哈哈……)
'http://www.knowsky.com
==================================================
UTF8 中文截取
由於UTF8 使用三個位元組…
所以傳統的substr 函數就沒轍了…
很多高手都寫了UTF8 中文字元截取函數…
這裡送上幾種:
1.先算再取
/**
* Author : Dummy | Zandy
* Email : [email protected] | hotmail.com
* Create : 200512
* Usage : echo join('', String::subString_UTF8('漢字', 0, 1));
*/
ini_set('display_errors', 1);
error_reporting(E_ALL ^ E_NOTICE);
class String {
function subString_UTF8($str, $start, $lenth)
{
$len = strlen($str);
$r = array();
$n = 0;
$m = 0;
for($i = 0; $i < $len; $i++) {
$x = substr($str, $i, 1);
$a = base_convert(ord($x), 10, 2);
$a = substr('00000000'.$a, -8);
if ($n < $start){
if (substr($a, 0, 1) == 0) {
}elseif (substr($a, 0, 3) == 110) {
$i += 1;
}elseif (substr($a, 0, 4) == 1110) {
$i += 2;
}
$n++;
}else{
if (substr($a, 0, 1) == 0) {
$r[] = substr($str, $i, 1);
}elseif (substr($a, 0, 3) == 110) {
$r[] = substr($str, $i, 2);
$i += 1;
}elseif (substr($a, 0, 4) == 1110) {
$r[] = substr($str, $i, 3);
$i += 2;
}else{
$r[] = '';
}
if (++$m >= $lenth){
break;
}
}
}
return $r;
} // End subString_UTF8
}// End String
echo join('', String::subString_UTF8('漢字', 0, 1));
2.先截後取這種方式涼鞋覺得很巧妙…
用傳統截取函數先截斷…
然後判斷中文單一字元是否被分割開…
如果是……則處理之…
要特別注意的是substr 函數的第三個參數必須大於3 …
至於為什麼不用涼鞋解釋了吧?
// A trim function to remove the last character of a utf-8 string
// by following instructions on http://en.wikipedia.org/wiki/UTF-8
// dotann
// usage: $str = utf8_trim(substr($str,0,50));
function utf8_trim($str) {
$len = strlen($str);
for ($i=strlen($str)-1; $i>=0; $i-=1){
$hex .= ' '.ord($str[$i]);
$ch = ord($str[$i]);
if (($ch & 128)==0) return(substr($str,0,$i));
if (($ch & 192)==192) return(substr($str,0,$i));
}
return($str.$hex);
}
$str = '漢字';
echo utf8_trim(substr($str,0,3));
3.還有其它方法,
例如007pig 為我們vBulletin 中文版所寫的函數…
短小精悍…
源碼不便放出…
對不住鳥…
今天就寫到這裡吧…
還有轉碼等問題沒寫…
最近忙…
有空繼續整理…
http://www.quchao.com/?p=6&pp=1