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

PHP 中英數字混排字符串按字節長度精準截取:避免亂碼的實用函數

     編輯:PHP 綜合知識

問題背景

GBK/GB2312 編碼下,中文字符佔 2 字節,英文數字佔 1 字節。直接用 substr($str, 0, $len) 按字節截取,極易在雙字節字符中間斷開,產生亂碼(如「中」)。

核心函數 smssubstr()

<?php
/**
 * 按顯示寬度(字節長度)截取混合編碼字符串
 * @param string $string 源字符串
 * @param int    $length 目標字節長度(中文算 2,英文算 1)
 * @return string 截取後字符串,不會產生半個漢字
 */
function smssubstr($string, $length) {
    if (strlen($string) <= $length) return $string;
    $result = '';
    for ($i = 0; $i < $length; $i++) {
        // ord > 127 視為雙字節字符首字節
        if (ord($string[$i]) > 127) {
            $result .= $string[$i] . $string[++$i]; // 連帶取下一字節
        } else {
            $result .= $string[$i];
        }
    }
    return $result;
}

// 示例:將長短信按 70 字節分段
$message = '親愛的用戶,您的驗證碼是 123456,請在 5 分鐘內輸入。';
$smsper = 70; // 單條短信字節上限
$smsnum = ceil(strlen($message) / $smsper);

for ($i = 1; $i <= $smsnum; $i++) {
    ${'smscontent' . $i} = smssubstr($message, $smsper);
    $message = str_replace(${'smscontent' . $i}, '', $message);
}
// 現在 $smscontent1, $smscontent2... 即為分段後的短信內容
?>

原理圖解

字符串:  中  國  a  b  中
字節:  D6 D0 B9 FA 61 62 D6 D0
索引:   0  1  2  3  4  5  6  7
length=5 截取過程:
i=0 ord(D6)>127 → 取 D6 D0 (i變1)  result="中"
i=2 ord(B9)>127 → 取 B9 FA (i變3)  result="中國"
i=4 ord(61)≤127 → 取 61            result="中國a"
i=5 ord(62)≤127 → 取 62            result="中國ab"
循環結束,完美避開半個漢字

現代替代方案(UTF-8 專用)

若項目已全面 UTF-8,請直接使用 mb_substr():

mb_internal_encoding('UTF-8');
echo mb_substr($str, 0, 20, 'UTF-8'); // 按字符數截取,天然支援多語言

或 mb_strimwidth($str, 0, 70, '...', 'UTF-8') 一步到位補省略號。

編碼檢測與統一建議

  1. 頁面頭部 header('Content-Type: text/html; charset=UTF-8');
  2. 數據庫連接 SET NAMES utf8mb4。
  3. 文件保存為 UTF-8 無 BOM。
  4. 統一內碼後,棄用本文函數,全面改用 mb_* 系列,避免維雙套邏輯。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved