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

PHP 判斷字串是否為 UTF-8 編碼:正則表達式實作解析

     編輯:關於C

問題背景

在處理多語系資料時,常需判斷字串是否為合法 UTF-8 編碼。PHP 內建 mb_check_encoding() 可直接完成,但若需自行實作或理解底層邏輯,可透過正則表達式檢查 UTF-8 位元組模式。

UTF-8 編碼規則速查

  • 單位元組 (ASCII):0xxxxxxx (0x00–0x7F)
  • 雙位元組:110xxxxx 10xxxxxx (0xC0–0xDF 開頭 + 0x80–0xBF 續位元組)
  • 三位元組:1110xxxx 10xxxxxx 10xxxxxx (0xE0–0xEF 開頭 + 兩個續位元組)
  • 四位元組:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (0xF0–0xF7 開頭 + 三個續位元組)

中文常見字多落在三位元組範圍(0xE0–0xEF 開頭)。

原始碼分析

function is_utf8($str) {
    // 正則 1:字串開頭符合「三位元組 UTF-8」模式
    $cond1 = preg_match('/^(['.chr(228).'-'.chr(233).']['.chr(128).'-'.chr(191).']['.chr(128).'-'.chr(191).']){1}/', $str);
    // 正則 2:字串結尾符合「三位元組 UTF-8」模式
    $cond2 = preg_match('/(['.chr(228).'-'.chr(233).']['.chr(128).'-'.chr(191).']['.chr(128).'-'.chr(191).']){1}$/', $str);
    // 正則 3:字串中包含「至少兩組連續三位元組 UTF-8」模式
    $cond3 = preg_match('/(['.chr(228).'-'.chr(233).']['.chr(128).'-'.chr(191).']['.chr(128).'-'.chr(191).']){2,}/', $str);

    return ($cond1 || $cond2 || $cond3);
}

程式碼解析

部分對應位元組範圍含義
chr(228)-chr(233)0xE4–0xE9三位元組 UTF-8 首位元組(涵蓋大部分中日韓統一表意文字)
chr(128)-chr(191)0x80–0xBFUTF-8 續位元組固定範圍
{1}—單組三位元組序列
{2,}—至少兩組連續三位元組序列

優缺點評析

優點

  • 無需安裝 mbstring 擴展即可運作。
  • 針對「含中文」字串的快速檢測效果尚可。

缺點與風險

  • 覆蓋範圍不完整:僅檢查 0xE4–0xE9 開頭的三位元組,漏掉 0xE0–0xE3、0xEA–0xEF 以及二/四位元組字符。
  • 誤判風險:純 ASCII 字串會回傳 false(實際上 ASCII 是合法 UTF-8 子集)。
  • 無法驗證完整結構:無法偵測「截斷的多位元組序列」、「過長編碼」等非法 UTF-8。

建議的最佳實務

// 1. 內建函數(推薦,PHP 5.2+)
function is_utf8_builtin($str) {
    return mb_check_encoding($str, 'UTF-8');
}

// 2. 完整正則(符合 RFC 3629,PHP 7.1+ 支援 \u 逃逸)
function is_utf8_strict($str) {
    return (bool)preg_match('~^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE-\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$~', $str);
}

// 3. 簡易檢查:嘗試轉碼,失敗即非 UTF-8
function is_utf8_pragmatic($str) {
    return @iconv('UTF-8', 'UTF-8//IGNORE', $str) === $str;
}

總結

原始函數可作為「字串可能包含中文」的啟發式快速判斷,但不可用於安全性驗證或嚴格編碼檢查。生產環境請優先使用 mb_check_encoding() 或完整 RFC 相容正則。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved