最近在做工具的時候遇到讀取兩個文件編碼不一致的情況,但實際情況并不是用iconv轉換就可以的那么簡單,因為其中一個編碼是ANSI,另一個是Unicode big endian,這時候用函數mb_detect_encoding 都識別不了編碼,更別想用幾個函數就能簡單轉換了。

不過google到了一個不錯的php類,引入即可。

 ?<?php
/** 字符編碼轉換類, ANSI、Unicode、Unicode big endian、UTF-8、UTF-8+Bom互相轉換

* Func:
* public convert 轉換
* private convToUtf8 把編碼轉為UTF-8編碼
* private convFromUtf8 把UTF-8編碼轉換為輸出編碼
*/
class CharsetConv{ // class start
 private $_in_charset = null; // 源編碼
 private $_out_charset = null; // 輸出編碼
 private $_allow_charset = array('utf-8', 'utf-8bom', 'ansi', 'unicode', 'unicodebe');
 /** 初始化
 * @param String $in_charset 源編碼
 * @param String $out_charset 輸出編碼
 */
 public function __construct($in_charset, $out_charset){
 $in_charset = strtolower($in_charset);
 $out_charset = strtolower($out_charset);
 // 檢查源編碼
 if(in_array($in_charset, $this->_allow_charset)){
 $this->_in_charset = $in_charset;
 }
 // 檢查輸出編碼
 if(in_array($out_charset, $this->_allow_charset)){
 $this->_out_charset = $out_charset;
 }

 }

 /** 轉換
 * @param String $str 要轉換的字符串
 * @return String 轉換后的字符串
 */
 public function convert($str){
 $str = $this->convToUtf8($str); // 先轉為utf8
 $str = $this->convFromUtf8($str); // 從utf8轉為對應的編碼
 return $str;
 }
 /** 把編碼轉為UTF-8編碼
 * @param String $str 
 * @return String
 */
 private function convToUtf8($str){
 if($this->_in_charset=='utf-8'){ // 編碼已經是utf-8,不用轉
 return $str;
 }
 switch($this->_in_charset){
 case 'utf-8bom':
 $str = substr($str, 3);
 break;
 case 'ansi':
 $str = iconv('GBK', 'UTF-8//IGNORE', $str);
 break;
 case 'unicode':
 $str = iconv('UTF-16le', 'UTF-8//IGNORE', substr($str, 2));
 break;
 case 'unicodebe':
 $str = iconv('UTF-16be', 'UTF-8//IGNORE', substr($str, 2));
 break;
 default:
 break;
 }
 return $str;
 }
 /** 把UTF-8編碼轉換為輸出編碼
 * @param String $str
 * @return String
 */
 private function convFromUtf8($str){

 if($this->_out_charset=='utf-8'){ // 輸出編碼已經是utf-8,不用轉
 return $str;
 }

 switch($this->_out_charset){
 case 'utf-8bom':
 $str = "\xef\xbb\xbf".$str;
 break;

 case 'ansi':
 $str = iconv('UTF-8', 'GBK//IGNORE', $str);
 break;

 case 'unicode':
 $str = "\xff\xfe".iconv('UTF-8', 'UTF-16le//IGNORE', $str);
 break;

 case 'unicodebe':
 $str = "\xfe\xff".iconv('UTF-8', 'UTF-16be//IGNORE', $str);
 break;

 default:
 break;
 }
 return $str;

 }

} // class end

?> 

使用方法:

 <?php
require "CharsetConv.class.php";

$str = file_get_contents('source/unicodebe.txt');

$obj = new CharsetConv('unicodebe', 'utf-8bom');//將Unicode big endian?轉化為utf-8帶bom
$response = $obj->convert($str);

file_put_contents('response/utf-8bom.txt', $response, true);
?> 
既然全部轉化為utf8,那么調用的php文件也必須是utf8編碼。

編碼科普

各種編碼在實際應用中比較容易混亂,下面從網上找的部分講解,相對比較容易理解,后門會加上自己對于這些編碼的理解。

一、ANSI
注意這里的ANSI編碼,并非ASCII編碼,雖然它確實有點迷惑人。在簡體中文系統下,ANSI編碼代表的就是GB2312編碼。對于一個ANSI文本,英文部分使用的就是ASCII編碼,而中文部分使用的就是GB2312編碼。
二、Unicode
Unicode是用2個字節表示全世界的符號,只要選擇Unicode編碼,所有的字符都會使用2個字節進行存儲,英文字符也不例外,說到Unicode編碼,一般默認指的是UTF-16/UCS-2, little endian這種實現。
三、Unicode big endian

Unicode big endian也是Unicode,只不過是另一種實現:UTF-16/UCS-2, big endian。
BIG-ENDIAN就是低位字節排放在內存的高端,高位字節排放在內存的低端。而LITTLE-ENDIAN正好相反。

例如“王”字:Unicode為738BH

若按Unicode-BE方式存儲,則是:73 8B

若按Unicode-LE方式存儲,就是:8B 73

四、UTF-8
UTF-8也是一種Unicode實現,因為Unicode是對全世界的所有符號進行了獨立的編碼,也就是獨一無二的,這個編碼與實現無關,UTF-8只是在這種獨立的編碼上面進行了重新的編碼,它是一種變長的格式,根據不同的編碼,字符可能占用1~4個字節。比如ASCII字符占用1個字節,而漢字一般都占用3個字節。

 

您的支持將鼓勵我們繼續創作!

[微信] 掃描二維碼打賞

[支付寶] 掃描二維碼打賞