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

PHP 多編碼相容的中英文字串截取函數(支援 UTF-8、GBK、Big5)

     編輯:PHP 相關知識

PHP 內建 substr() 按位元組截取,對多位元組編碼(UTF-8、GBK、Big5)的中文會導致亂碼。本文提供兩個可直接使用的函數:mb_substr 封裝版(推薦)與純 PHP 實作版(無需 mbstring 擴展),均支援指定編碼、起始位置、長度、尾綴。

方案一:優先使用 mbstring 擴展(標準、高效)

function mbCut($string, $start, $length, $charset = 'UTF-8', $suffix = '...') {
    if (function_exists('mb_substr')) {
        $slice = mb_substr($string, $start, $length, $charset);
        return $suffix && mb_strlen($string, $charset) > $start + $length ? $slice . $suffix : $slice;
    }
    // fallback 見方案二
    return selfCut($string, $start, $length, $charset, $suffix);
}

方案二:純 PHP 正則實作(無 mbstring 環境適用)

function selfCut($str, $start, $length, $charset = 'UTF-8', $suffix = '...') {
    // 定義各編碼的字元正則
    $patterns = [
        'utf-8'   => '/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/',
        'gb2312'  => '/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/',
        'gbk'     => '/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/',
        'big5'    => '/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/',
    ];
    $charset = strtolower($charset);
    if (!isset($patterns[$charset])) $charset = 'utf-8';

    preg_match_all($patterns[$charset], $str, $matches);
    $chars = $matches[0];
    $slice = implode('', array_slice($chars, $start, $length));

    if ($suffix && count($chars) > $start + $length) {
        $slice .= $suffix;
    }
    return $slice;
}

方案三:手動解析 UTF-8 位元組(教學用,效能較低)

function utf8SubstrManual($str, $start, $length) {
    $len = strlen($str);
    $result = [];
    $count = 0;
    $picked = 0;

    for ($i = 0; $i < $len; $i++) {
        $byte = $str[$i];
        $ord = ord($byte);
        $charLen = 1;
        if (($ord & 0x80) == 0x00) $charLen = 1;      // 0xxxxxxx
        elseif (($ord & 0xE0) == 0xC0) $charLen = 2; // 110xxxxx
        elseif (($ord & 0xF0) == 0xE0) $charLen = 3; // 1110xxxx
        elseif (($ord & 0xF8) == 0xF0) $charLen = 4; // 11110xxx

        if ($count >= $start && $picked < $length) {
            $result[] = substr($str, $i, $charLen);
            $picked++;
        }
        $count++;
        $i += $charLen - 1;
    }
    return implode('', $result);
}
// 使用:join('', utf8SubstrManual($str, 0, 10));

使用範例

$text = "PHP中文截取測試abcdefg";

// UTF-8 環境
echo mbCut($text, 0, 10);           // PHP中文截取測試a...
echo selfCut($text, 0, 10, 'UTF-8'); // 同上

// GBK 環境(需確保檔案編碼為 GBK)
// echo selfCut($text, 0, 10, 'GBK');

效能與選擇建議

方案優點缺點適用場景
mb_substr原生 C 實作、極快、支援所有編碼需安裝 mbstring 擴展現代 PHP 專案首選
正則 preg_match_all純 PHP、無擴展依賴大字串效能較差、正則複雜舊環境、共享主機無 mbstring
手動位元組解析邏輯清晰、教學價值高效能最差、易出錯學習 UTF-8 結構、極特殊環境

常見坑點

  • 檔案編碼與宣告一致:PHP 檔案本身必須以目標編碼(UTF-8 無 BOM)儲存,否則字面字串會被誤判。
  • 資料庫連線編碼:SET NAMES utf8mb4 確保讀寫一致。
  • 長度單位:以上函數的 $length 皆為 字元數,非位元組數。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved