處理來源未知編碼的字串(如爬蟲資料、舊系統匯入)時,需自動判斷編碼並統一轉為 UTF-8。本文提供基於位元組特徵的偵測函數,無需 mb_detect_encoding(不準確),直接解析位元組模式。
1110xxxx 10xxxxxx 10xxxxxx(首位元組 0xE0~0xEF,後續 0x80~0xBF)。110xxxxx 10xxxxxx(首位元組 0x81~0xFE,次位元組 0x40~0xFE,排除 0x7F)。<?php
/**
* 自動偵測字串編碼並轉換為指定輸出編碼
* @param string $string 輸入字串
* @param string $outEncoding 目標編碼,預設 UTF-8
* @return string 轉碼後字串
*/
function safeEncoding($string, $outEncoding = 'UTF-8') {
$encoding = 'UTF-8'; // 預設假設為 UTF-8
$len = strlen($string);
for ($i = 0; $i < $len; $i++) {
$byte = ord($string[$i]);
// ASCII 直接跳過
if ($byte < 128) continue;
// 檢測 UTF-8 三位元組模式:1110xxxx 10xxxxxx 10xxxxxx
if (($byte & 0xE0) === 0xE0) { // 0xE0 = 224
// 確保還有至少 2 個位元組
if ($i + 2 >= $len) break;
$b1 = ord($string[$i+1]);
$b2 = ord($string[$i+2]);
if (($b1 & 0xC0) === 0x80 && ($b2 & 0xC0) === 0x80) { // 10xxxxxx
$encoding = 'UTF-8';
break; // 找到確定特徵,停止偵測
}
}
// 檢測 GBK/GB2312 兩位元組模式:110xxxxx 10xxxxxx
if (($byte & 0xC0) === 0xC0) { // 0xC0 = 192
if ($i + 1 >= $len) break;
$b1 = ord($string[$i+1]);
if (($b1 & 0xC0) === 0x80) {
$encoding = 'GB2312'; // GBK 相容 GB2312
break;
}
}
}
// 已是目標編碼直接返回
if (strtoupper($encoding) === strtoupper($outEncoding)) {
return $string;
}
// 使用 iconv 轉碼,//IGNORE 忽略無法轉換字元
return iconv($encoding, $outEncoding . '//IGNORE', $string);
}
// 使用範例
$str_gbk = "測試字串"; // 假設為 GBK 編碼
$str_utf8 = safeEncoding($str_gbk, 'UTF-8');
echo $str_utf8; // 正常顯示中文
?>
function detectEncodingWithBOM($content) {
// UTF-8 BOM: EF BB BF
if (substr($content, 0, 3) === "\xEF\xBB\xBF") return 'UTF-8';
// UTF-16 LE BOM: FF FE
if (substr($content, 0, 2) === "\xFF\xFE") return 'UTF-16LE';
// UTF-16 BE BOM: FE FF
if (substr($content, 0, 2) === "\xFE\xFF") return 'UTF-16BE';
// UTF-32 LE BOM: FF FE 00 00
if (substr($content, 0, 4) === "\xFF\xFE\x00\x00") return 'UTF-32LE';
// UTF-32 BE BOM: 00 00 FE FF
if (substr($content, 0, 4) === "\x00\x00\xFE\xFF") return 'UTF-32BE';
return safeEncoding($content); // 回退到位元組特徵偵測
}
| 方法 | 準確度 | 速度 | 適用場景 |
|---|---|---|---|
| mb_detect_encoding | 中(易誤判短字串) | 中 | 快速原型、非關鍵路徑 |
| 本文位元組特徵法 | 高(明確模式匹配) | 快(單趟掃描) | 生產環境、大量資料清洗 |
| 檢測 BOM + 位元組特徵 | 最高 | 快 | 檔案讀取、跨系統匯入 |
| 統計語言模型(如 PHP-ML) | 極高 | 慢 | 極短字串、混合編碼 |
iconv -l 查看系統支援列表,常用別名:GB2312、GBK、CP936、UTF-8、UTF-16。//IGNORE 丟棄無法轉換字元,//TRANSLIT 嘗試轉換為相近字元(如全形轉半形),視需求選擇。<?php
class EncodingHelper {
public static function toUtf8($string) {
return self::safeEncoding($string, 'UTF-8');
}
public static function safeEncoding($string, $outEncoding = 'UTF-8') {
// ... 上述函數本體 ...
}
public static function detectFile($filepath) {
$content = file_get_contents($filepath);
return self::detectEncodingWithBOM($content);
}
}
?>