在處理多語系資料時,常需判斷字串是否為合法 UTF-8 編碼。PHP 內建 mb_check_encoding() 可直接完成,但若需自行實作或理解底層邏輯,可透過正則表達式檢查 UTF-8 位元組模式。
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–0xBF | UTF-8 續位元組固定範圍 |
{1} | — | 單組三位元組序列 |
{2,} | — | 至少兩組連續三位元組序列 |
mbstring 擴展即可運作。false(實際上 ASCII 是合法 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 相容正則。