對接舊系統、第三方 API、用戶輸入時,字串編碼往往不統一(UTF-8、GBK、GB2312 混雜)。若不檢測直接 iconv 會產生亂碼或截斷。本文提供純 PHP 函式,掃描字串位元組特徵自動判斷編碼並安全轉碼。
1110xxxx (0xE0-0xEF),後兩位元組 10xxxxxx (0x80-0xBF)。110xxxxx (0x81-0xFE),次位元組 10xxxxxx (0x40-0xFE, 除 0x7F)。function safeEncoding($string, $outEncoding = 'UTF-8') {
$encoding = "UTF-8"; // 預設
$len = strlen($string);
for ($i = 0; $i < $len; $i++) {
$byte = ord($string[$i]);
// ASCII 直接跳過
if ($byte < 128) continue;
// 檢測 UTF-8 三位元組特徵
if (($byte & 0xE0) === 0xE0) { // 1110xxxx
// 確保還有 2 個位元組
if ($i + 2 < $len) {
$b2 = ord($string[$i+1]);
$b3 = ord($string[$i+2]);
if (($b2 & 0xC0) === 0x80 && ($b3 & 0xC0) === 0x80) {
$encoding = "UTF-8";
break; // 發現明確 UTF-8 序列,直接判定
}
}
}
// 檢測 GBK/GB2312 兩位元組特徵
if (($byte & 0xC0) === 0xC0) { // 110xxxxx (實際 GBK 首位元組範圍 0x81-0xFE)
if ($i + 1 < $len) {
$b2 = ord($string[$i+1]);
if (($b2 & 0xC0) === 0x80) { // 簡略判斷:次位元組高兩位為 10
$encoding = "GB2312"; // iconv 識別 GB23312 實為 GBK 超集
break;
}
}
}
}
// 已是目標編碼直接返回
if (strtoupper($encoding) === strtoupper($outEncoding)) {
return $string;
}
// 執行轉碼
return @iconv($encoding, $outEncoding . '//IGNORE', $string);
}
<?php
// 模擬 GBK 字串
$gbkStr = iconv('UTF-8', 'GBK', '你好世界');
echo "原始編碼偵測: " . mb_detect_encoding($gbkStr) . "\n";
$utf8Str = safeEncoding($gbkStr, 'UTF-8');
echo "轉碼後: $utf8Str\n";
// 已是 UTF-8 不重複轉碼
$utf8Str2 = safeEncoding('已經是UTF-8', 'UTF-8');
echo "無轉碼: $utf8Str2\n";
?>
EF BB BF = UTF-8,FF FE/FE FF = UTF-16),優先級高於內容掃描。mbstring 擴展:生產環境首選 mb_detect_encoding() + mb_convert_encoding(),官方維護、支援編碼更全、處理邊界情況更健壯。iconv。自動編碼偵測是跨系統整合的基礎設施,配合 mbstring 或自研函式,讓亂碼問題成為歷史。