| 編碼 | 中文字節數 | 英文/數字字節數 | 備註 |
| UTF-8 | 3 | 1 | 現代 Web 標準,支援全字符集 |
| GBK/GB2312 | 2 | 1 | 中文舊標準,不支援生僻字/Emoji |
| UTF-16 | 2 或 4 | 2 | Java/JS 內部編碼 |
實用技巧:計算中英混排「顯示寬度/占位」
場景:表格列寬、截取摘要、終端對齊。規則:中文寬度 2,英文/數字/標點寬度 1。
function str_display_width(string $str, string $encoding = 'UTF-8'): int {
// 原理:總字節數 + 字符數 = (中文×3 + 英文×1) + (中文+英文) = 中文×4 + 英文×2
// 顯示寬度 = 中文×2 + 英文×1 = (總字節數 + 字符數) / 2
return (strlen($str) + mb_strlen($str, $encoding)) / 2;
}
$test = '中文a字1符';
echo "顯示寬度: " . str_display_width($test); // 10 (4×2 + 1 + 1)
截取中英混排字符串(不截半個漢字)
// mb_substr 按字符截取,安全
$summary = mb_substr($longText, 0, 50, 'UTF-8') . '...';
// 如果必須用 substr(字節截取),需配合檢測
function safe_substr($str, $len, $encoding = 'UTF-8') {
if (mb_strlen($str, $encoding) <= $len) return $str;
return mb_substr($str, 0, $len, $encoding) . '...';
}
常見陷阱與避坑指南
1. 忘記啟用 mbstring 擴展
; php.ini
extension=mbstring ; 取消註釋
; Windows: extension=php_mbstring.dll
2. 不指定編碼依賴內部編碼
// ❌ 風險:內部編碼可能被 mb_internal_encoding() 修改
mb_strlen($str);
// ✅ 顯式指定
mb_strlen($str, 'UTF-8');
3. 文件編碼與聲明不一致
- PHP 文件保存為 UTF-8 無 BOM
- HTML
<meta charset="UTF-8">
- 資料庫連接
SET NAMES utf8mb4
- 三者統一,才能保證 strlen/mb_strlen 行為可預期
4. 陣列/對象傳入 strlen
strlen(['a', 'b']); // 警告:期望 string,返回 1 (Array 轉字符串)
mb_strlen(['a', 'b']); // 警告 + false
5. 統計字符頻次
// count_chars 僅支援單字節編碼
// 多字節編碼用:
preg_match_all('/./u', $str, $matches); // u 修飾符按 Unicode 字符匹配
$freq = array_count_values($matches[0]);
效能對比
- strlen:C 級別極快,O(1) 返回已知字節長度(PHP 字符串結構存儲長度)
- mb_strlen:需遍歷字節解碼統計字符數,O(n),慢約 5-10 倍
- 高頻調用場景(如百萬級循環)優先用 strlen,僅在需字符數時用 mb_strlen
總結速查表
| 需求 | 推薦函數 | 示例 |
| 獲取字節長度(存儲、傳輸、緩存 key) | strlen() | strlen($json) |
| 獲取字符數(顯示、驗證、截取) | mb_strlen($str, 'UTF-8') | mb_strlen($username, 'UTF-8') |
| 計算顯示寬度(終端、表格、PDF) | (strlen + mb_strlen) / 2 | str_display_width($text) |
| 安全截取 | mb_substr($str, 0, $len, 'UTF-8') | mb_substr($title, 0, 30, 'UTF-8') |
| 按字符遍歷 | preg_match_all('/./u', $str, $m) | foreach ($m[0] as $char)... |
結語
搞清「字節」與「字符」的區別,始終顯式指定 UTF-8 編碼,統一文件/數據庫/頁面編碼,即可徹底解決 PHP 字符串長度計算的所有疑難雜症。
- 上一篇文章: PHP 函數進階:遞歸算法實戰、return 與 echo 的本質區別、變量作用域
- 下一篇文章: CodeIgniter 上傳 RAR/ZIP 壓縮檔失效解決:MIME 類型完整配置指南
Copyright ©
程式碼之家 All Rights Reserved