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

PHP Substr 庫函式:支援 GBK/Big5 中文截取的實現解析

     編輯:PHP 相關知識

函式定位與適用範圍

此 Substring() 函式專為 GB18030、GB2312、Big5 編碼設計,不支援 UTF-8。核心邏輯:逐位元組掃描,依編碼區間判斷雙位元組字元,正確計數與截取。

原始碼深度解析

function Substring($str, $max) {
    $cnt = 0;      // 實際字元計數
    $index = 0;    // 當前位元組索引
    $output = '';  // 輸出緩衝

    while ($cnt < $max && $index < strlen($str)) {
        $output .= $str[$index];

        // Big5 範圍判斷:首位元組 0x81-0xFE,次位元組 0x40-0x7E 或 0xA1-0xFE
        if (ord($str[$index]) >= 0x81 && ord($str[$index]) <= 0xfe) {
            if ($index + 1 < strlen($str)) {
                $next = ord($str[$index + 1]);
                if (($next >= 0x40 && $next < 0x7e) || ($next >= 0xa1 && $next <= 0xfe)) {
                    $index++;
                    $output .= $str[$index];
                }
            }
        }
        // GB2312 範圍判斷:首位元組 0xA1-0xF7,次位元組 0xA1-0xFE
        else if (ord($str[$index]) >= 0xa1 && ord($str[$index]) <= 0xf7) {
            $output .= $str[$index];
            if ($index + 1 < strlen($str)) {
                if (ord($str[$index + 1]) >= 0xa1 && ord($str[$index + 1]) < 0xfe) {
                    $index++;
                    $output .= $str[$index];
                }
            }
        }
        // ASCII 單位元組字元
        else {
            // 無需額外處理
        }

        $cnt++;
        $index++;
    }
    return $output;
}

關鍵技術點

  1. 雙編碼兼容:同一迴圈內分支處理 Big5 與 GB2312,適配繁簡體混雜場景
  2. 邊界保護:$index + 1 < strlen($str) 防止越界讀取
  3. 字元級計數:$cnt 計算顯示字元數而非位元組數

局限與改進方向

  • ❌ 不支援 UTF-8(多位元組變長編碼邏輯完全不同)
  • ❌ 無省略號自動補全功能
  • ❌ 效能隨字串長度線性增長,長文本場景建議改用 mb_substr
  • ✅ 可擴充:新增 $encoding 參數,內部路由至 mb_substr 或保留舊邏輯

現代化替代方案

// 統一入口,自動適配編碼
function safe_substr($str, $start, $length, $encoding = 'UTF-8') {
    if (function_exists('mb_substr')) {
        return mb_substr($str, $start, $length, $encoding);
    }
    // 降級:僅支援 GBK/Big5
    if (in_array(strtoupper($encoding), ['GBK', 'GB2312', 'BIG5'])) {
        return Substring($str, $length); // 簡化版
    }
    // 最後防線:單純位元組截取(風險自負)
    return substr($str, $start, $length);
}

結語

歷史遺留專案中此類函式仍有價值,但新專案請直接擁抱 mbstring 與 UTF-8,從根源消除編碼地獄。

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