首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 字符串編碼檢測與轉換完全指南:mbstring、正則與實戰函數庫

     編輯:PHP 相關知識

核心函數:mb_detect_encoding()

<?php
$str = "測試字符串";
$encoding = mb_detect_encoding($str, ['UTF-8', 'GB2312', 'GBK', 'BIG5'], true);
echo $encoding; // UTF-8

// 嚴格模式:無法確定時返回 false
$encoding = mb_detect_encoding($str, 'UTF-8', true);

前提:php.ini 啟用 extension=mbstring。

無 mbstring 環境下的純 PHP 實現

1. 判斷是否為 UTF-8(正則法,RFC 3629 標準)

function is_utf8($string) {
    return (bool)preg_match('%^(?:
        [\x09\x0A\x0D\x20-\x7E]              # ASCII
      | [\xC2-\xDF][\x80-\xBF]               # non-overlong 2-byte
      |  \xE0[\xA0-\xBF][\x80-\xBF]         # excluding overlongs
      | [\xE1-\xEC\xEE-\xEF][\x80-\xBF]{2}  # straight 3-byte
      |  \xED[\x80-\x9F][\x80-\xBF]         # excluding surrogates
      |  \xF0[\x90-\xBF][\x80-\xBF]{2}      # planes 1-3
      | [\xF1-\xF3][\x80-\xBF]{3}           # planes 4-15
      |  \xF4[\x80-\x8F][\x80-\xBF]{2}      # plane 16
    )*$%xs', $string);
}

2. 判斷是否為 GB2312/GBK(字節特徵法)

function is_gb2312($str) {
    for ($i = 0; $i < strlen($str); $i++) {
        $v = ord($str[$i]);
        if ($v > 127) { // 高位字節
            if ($v >= 228 && $v <= 233) { // UTF-8 三字節首字節範圍
                if ($i + 2 >= strlen($str)) return true; // 長度不足視為 GBK
                $v1 = ord($str[$i+1]);
                $v2 = ord($str[$i+2]);
                if ($v1 >= 128 && $v1 <= 191 && $v2 >= 128 && $v2 <= 191) {
                    return false; // 符合 UTF-8 續字節特徵
                }
            }
            return true; // 其他高位字節視為 GBK
        }
    }
    return true; // 純 ASCII 兼容視為 GBK
}

3. 智能轉換函數:統一輸出 UTF-8

function to_utf8($str) {
    if (is_utf8($str)) return $str;
    // 嘗試常見中文編碼
    foreach (['GBK', 'GB2312', 'BIG5'] as $enc) {
        $converted = @iconv($enc, 'UTF-8//IGNORE', $str);
        if ($converted !== false && is_utf8($converted)) {
            return $converted;
        }
    }
    return $str; // 實在無法識別則原樣返回
}

mbstring 完整轉換工作流

<?php
// 1. 檢測編碼
$encoding = mb_detect_encoding($input, ['UTF-8', 'GBK', 'GB2312', 'BIG5'], true);

// 2. 統一轉為 UTF-8 內部處理
$utf8 = mb_convert_encoding($input, 'UTF-8', $encoding);

// 3. 業務邏輯處理...

// 4. 輸出時按需轉碼
$output = mb_convert_encoding($utf8, 'GBK', 'UTF-8'); // 給老系統
// 或
header('Content-Type: text/html; charset=UTF-8');
echo $utf8; // 現代 Web 直接輸出 UTF-8

常見編碼問題速查表

現象原因解決
亂碼UTF-8 數據被當作 GBK 讀取確保 HTTP Header、HTML meta、PHP 內部、MySQL 連接全鏈路 UTF-8
? 佔位符GBK 數據強行按 UTF-8 解碼,非法字節被替換正確指定源編碼 iconv('GBK', 'UTF-8//IGNORE', $str)
iconv 返回 false源編碼判斷錯誤或包含非法字節用 //IGNORE 或 //TRANSLIT 忽略/轉義非法字節
中文截斷亂碼按字節截取多字節字符用 mb_substr($str, 0, 10, 'UTF-8')

最佳實踐原則

  1. 全棧 UTF-8:HTML ``、HTTP Header、PHP `default_charset = "UTF-8"`、MySQL `utf8mb4`、資源文件無 BOM UTF-8。
  2. 入口統一轉碼:所有外部輸入(`$_GET`、`$_POST`、文件讀取、API 響應)在進入業務邏輯前統一 to_utf8()。
  3. 數據庫連接設置:PDO `charset=utf8mb4` / mysqli `set_charset('utf8mb4')`。
  4. 避免雙重編碼:已是 UTF-8 的數據不要再次 iconv('UTF-8', 'UTF-8', ...)。
  5. 測試用例覆蓋:收集 ASCII、中文、Emoji、稀有字、混合編碼樣本,自動化測試編碼處理函數。

性能提示

  • mb_detect_encoding 較慢(需嘗試多種編碼),高頻調用處緩存結果或預先約定編碼。
  • iconv 比 mb_convert_encoding 略快,大批量轉碼優先用 iconv。
  • 純 ASCII 判斷可用 !preg_match('/[\\x80-\\xFF]/', $str) 極快排除。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved