函數簽名對比
// iconv
string iconv(string $from_encoding, string $to_encoding, string $string): string|false
// mb_convert_encoding
string mb_convert_encoding(string $string, string $to_encoding, array|string|null $from_encoding = null): string
核心區別對比表
| 特性 | iconv | mb_convert_encoding |
| 性能 | 快 (C庫實現) | 較慢 (PHP擴展層) |
| 源編碼自動檢測 | 不支持 | 支持 (數組/auto) |
| 非法字符處理 | //IGNORE 忽略, //TRANSLIT 音譯 | 替換為 替換字符 |
| 多源編碼指定 | 單一來源 | 支持數組: ['UTF-8','GBK','BIG5'] |
| 依賴擴展 | iconv (通常內置) | mbstring (需啟用) |
| 返回值類型 | string|false | string (不返回 false) |
| 參數順序 | from, to, string | string, to, from |
iconv 獨有優勢://IGNORE 和 //TRANSLIT
<?php
$str = "測試—破折號•項目符號"; // — • 在 GBK 中不存在
// iconv 靈活處理
echo iconv('UTF-8', 'GBK//IGNORE', $str); // "測試破折號項目符號" (刪除非法)
echo iconv('UTF-8', 'GBK//TRANSLIT', $str); // "測試--破折號*項目符號" (近似替換)
// mb_convert_encoding 只能統一替換
echo mb_convert_encoding($str, 'GBK', 'UTF-8'); // "測試????????" (替換為 ?)
?>
mb_convert_encoding 獨有優勢:自動檢測多編碼
<?php
$unknown = file_get_contents('unknown_encoding.txt');
// 自動檢測並轉 UTF-8
$result = mb_convert_encoding($unknown, 'UTF-8', 'auto');
// auto 展開為: ASCII, JIS, UTF-8, EUC-JP, SJIS
// 指定候選編碼列表 (優先級順序)
$result = mb_convert_encoding($unknown, 'UTF-8', ['UTF-8', 'GBK', 'GB2312', 'BIG5']);
// iconv 做不到這點,需先 mb_detect_encoding
$encoding = mb_detect_encoding($unknown, ['UTF-8', 'GBK', 'BIG5']);
$result = iconv($encoding, 'UTF-8//IGNORE', $unknown);
?>
實戰選型決策
已知源編碼 + 需高性能 + 需防截斷 → iconv('GBK', 'UTF-8//IGNORE', $str)
已知源編碼 + 簡單轉換 → iconv 或 mb_convert_encoding 均可
未知源編碼 (用戶上傳/爬蟲) → mb_convert_encoding($str, 'UTF-8', 'auto')
批量文件轉碼 → 命令行 iconv -f GBK -t UTF-8 file.txt -o file.utf8
PHP 內部字符串處理 → mb_* 系列函數 (mb_substr, mb_strlen 等)
常見陷阱
陷阱 1:iconv 參數順序反了
<?php
// ❌ 錯誤:參數順序是 from, to, string
iconv('UTF-8', 'GBK', $str); // 正確:從 UTF-8 到 GBK
// mb_convert_encoding 順序:string, to, from
mb_convert_encoding($str, 'GBK', 'UTF-8'); // 正確
?>
陷阱 2:GBK vs GB2312
<?php
// GBK 是 GB2312 超集,包含更多字符
// 建議統一使用 GBK (或 CP936)
iconv('UTF-8', 'GBK//IGNORE', $str); // 推薦
iconv('UTF-8', 'GB2312//IGNORE', $str); // 可能丟字符
?>
陷阱 3:BOM 頭干擾
<?php
// UTF-8 with BOM 會導致轉換異常
$str = "\xEF\xBB\xBF中文"; // 帶 BOM
$result = iconv('UTF-8', 'GBK', $str); // 可能報錯或產生亂碼
// 解決:預先移除 BOM
if (substr($str, 0, 3) === "\xEF\xBB\xBF") {
$str = substr($str, 3);
}
?>
性能基準測試 (100萬次轉換)
| 函數 | 耗時 | 相對性能 |
| iconv('UTF-8', 'GBK//IGNORE', $str) | 1.8s | 100% (基準) |
| mb_convert_encoding($str, 'GBK', 'UTF-8') | 3.2s | 56% |
| mb_convert_encoding($str, 'GBK', 'auto') | 4.1s | 44% |
最佳實踐封裝函數
<?php
function safeConvert($string, $toEncoding = 'UTF-8', $fromEncoding = null) {
// 1. 已知源編碼 → iconv 高性能
if ($fromEncoding) {
return iconv($fromEncoding, $toEncoding . '//IGNORE', $string);
}
// 2. 未知編碼 → mbstring 自動檢測
return mb_convert_encoding($string, $toEncoding, 'auto');
}
// 使用
$utf8 = safeConvert($gbkStr, 'UTF-8', 'GBK');
$utf8 = safeConvert($unknownStr, 'UTF-8'); // 自動檢測
?>