天天看點

用ajax送出表單時中文亂碼解決方案

掉坑裡了,遭遇到了js與PHP對表單中中文編碼、解碼方法不統一的問題。

當年上學的時候,對ms很是不屑,總是想玩一些與衆不同的東西,玩linux、freebsd,玩opera,玩C++builder。當我做了一個網絡開發者,才發現自己曾經是多麼的幼稚,才開始懷念IE一統天下的那段美好時光。做一個網絡開發者最大的苦惱是什麼?對我來說這個問題的答案是:不統一的标準。如果你也經曆過下面這些事情,我想你會同意我的看法:

一個在IE下看起來很正常很美觀的頁面,在其它的浏覽器中卻一踏糊塗,反之亦然;

一段在IE下工作得很完美的js代碼,在其它的浏覽器中卻一點反應都沒有,反之亦然;

......

也許個性真的是學生才能玩的東西。

不說廢話了,說說我遇到的這個問題吧。要做一個無重新整理的評論,類似于discuz5.5中的無重新整理回帖。在送出表單的時候遇到了問題,通過ajax送出到處理腳本的中文字元串被轉成了utf-8的格式,于是在往資料庫裡執行插入的時候出現了亂碼。搜了一把卻沒有發現解決方案,于是開始自己摸索,摸索的過程中寫了下面的函數:

//将類似'%D5%E2%D5%E2%D5%E2%D5%E2%D5%E2%D5%E2'解碼,傳回一個正常的字元串

function chardecode($str,$sep='%')

{

 $string = str_replace($sep,'',$str);

 $len = strlen($string);

 $strdecode = '';

 for ($i=0;$i<$len;$i+=2){

  $num1 = substr($string,$i,2);

  $num1 = hexdec($num1);

  $i+=2;

  $num2 = substr($string,$i,2);

  $num2 = hexdec($num2);

  $strdecode .= chr($num1).chr($num2);

 }

 return $strdecode;

}

其實這個函數的作用類似于urlencode(),比它強的地方在于可以自己設定每個字元間的分隔符。代碼已經足夠簡單了,用到了兩個不太常用的函數,hexdex()和chr()。前者的作用是将一個16進制的數字轉換成10進制,後者是将一個數字轉換成對應的aiscII字元。

然而這個函數并沒能幫我解決問題,亂碼依舊。其實解決這個問題主要難點是發現問題到底出在哪裡,我并不是一上來就發現中文字元被轉成了utf-8格式,隻能一點點的摸索,找到了原因這個問題也就不難解決了。

這裡用的是pnews裡的一個utf-8轉gb2312的函數,放出來與大家共享:

function u2g( $instr ) {

 $fp = fopen( '../language/unicode-gb.tab', 'r' );

 $len = strlen($instr);

 $outstr = '';

 for( $i = $x = 0 ; $i < $len ; $i++ ) {

  $b1 = ord($instr[$i]);

  if( $b1 < 0x80 ) {

   $outstr[$x++] = chr($b1);

#   printf( "[%02X]", $b1);

  }

  elseif( $b1 >= 224 ) { # 3 bytes UTF-8

   $b1 -= 224;

   $b2 = ord($instr[$i+1]) - 128;

   $b3 = ord($instr[$i+2]) - 128;

   $i += 2;

   $uc = $b1 * 4096 + $b2 * 64 + $b3 ;

   fseek( $fp, $uc * 2 );

   $gb = fread( $fp, 2 );

   $outstr[$x++] = $gb[0];

   $outstr[$x++] = $gb[1];

#   printf( "[%02X%02X]", ord($gb[0]), ord($gb[1]));

  elseif( $b1 >= 192 ) { # 2 bytes UTF-8

   printf( "[%02X%02X]", $b1, ord($instr[$i+1]) );

   $b1 -= 192;

   $b2 = ord($instr[$i]) - 128;

   $i++;

   $uc = $b1 * 64 + $b2 ;

 fclose($fp);

 if( $instr != '' ) {

#  echo '##' . $instr . " becomes " . join( '', $outstr) . "<br>n";

  return join( '', $outstr);

注意函數中用到了一個碼表:unicode-gb.tab,附件中的就是了。使用的時候你得根據實際情況把函數中的第一句改成碼表實際存放的位置。

     本文轉自wfyang 51CTO部落格,原文連結:http://blog.51cto.com/wfyang/28751,如需轉載請自行聯系原作者