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

PHP 解決 substr() 中文截取亂碼完整方案:mb_substr 與自訂函數實作

     編輯:PHP 相關知識

PHP 中文字串截取亂碼問題根因與解決方案

PHP 內建 substr() 函數按位元組截取字串,對於多位元組編碼(UTF-8 中文佔 3 位元組、Big5 佔 2 位元組)會導致中文字元被切斷,產生亂碼。本文詳細分析問題成因,提供多種解決方案。

問題根因分析

  • UTF-8 編碼:1 個中文字元 = 3 位元組,英文 = 1 位元組
  • substr():單純按位元組計算長度,不識別字元邊界
  • 結果:截取長度落在中文字元中間時,產生無效位元組序列,瀏覽器顯示亂碼

方案一:mb_substr() 多位元組安全函數(推薦)

$str = "你好世界 Hello World";

// 正確截取前 6 個字元(包含中英文)
$result = mb_substr($str, 0, 6, 'UTF-8'); 
// 結果:"你好世界"

echo mb_substr($str, 0, 10, 'UTF-8'); // "你好世界 Hello"

優點:原生支援、效能佳、語法簡單
前提:PHP 需安裝 mbstring 擴充(現代環境通常預設啟用)

方案二:自訂 UTF-8 字元感知截取函數

function utf8_substr($str, $start, $length) {
    $result = '';
    $strLen = strlen($str);
    $charCount = 0;
    $bytePos = 0;
    
    for ($i = 0; $i < $strLen; $i++) {
        $byte = ord($str[$i]);
        
        // 判斷 UTF-8 字元位元組數
        if ($byte < 0x80) {
            $charBytes = 1;      // 0xxxxxxx (ASCII)
        } elseif ($byte < 0xE0) {
            $charBytes = 2;      // 110xxxxx 10xxxxxx
        } elseif ($byte < 0xF0) {
            $charBytes = 3;      // 1110xxxx 10xxxxxx 10xxxxxx (中文)
        } else {
            $charBytes = 4;      // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        }
        
        if ($charCount >= $start && $charCount < $start + $length) {
            $result .= substr($str, $i, $charBytes);
        }
        
        $charCount++;
        $i += $charBytes - 1; // 跳過後續位元組
    }
    
    return $result;
}

方案三:利用 preg_split 切割字元陣列(簡單但效能較低)

function mb_substr_alt($str, $start, $length) {
    $chars = preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY);
    return implode('', array_slice($chars, $start, $length));
}

效能比較與選擇建議

方法效能相依性建議場景
mb_substr()最高mbstring生產環境首選
自訂位元組解析中等無無 mbstring 環境
preg_split 方案較低PCRE快速原型、短字串

常見應用場景:文章摘要產生

function generateExcerpt($content, $length = 200) {
    // 移除 HTML 標籤
    $text = strip_tags($content);
    // 正確截取
    $excerpt = mb_substr($text, 0, $length, 'UTF-8');
    // 若有截斷,加上省略號
    if (mb_strlen($text, 'UTF-8') > $length) {
        $excerpt .= '...';
    }
    return $excerpt;
}

掌握多位元組字串處理,是 PHP 開發中文應用的基礎功力。建議專案統一使用 mb_* 系列函數,並設定 mb_internal_encoding('UTF-8') 避免重複指定編碼參數。

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