PHP的中文字符串截取

在PHP中,substr()函数截取带有中文字符串的话,可能会出现乱码,这是因为中西文一个字节所占有的字节数不一样,而substr()的长度参数是按照字节去算的。substr()截取位数不准确,substr()硬生生地将一个中文字符“锯”成两半,造成断开的字符会把其后的码位拉过来一起做一个字,所以出现了PHP substr()截取中文乱码现象。

在GB2312编码时,一个中文占2个字节,英文为1个字节,而在UTF-8编码当中,一个中文可能占有2个或3个字节,英文或半角标点占1字节。

0. 原生解决方案

PHP中有原生的解决方案,mb_substr()方法。需要开启mbstring扩展,方法:
在php的配置文件中,寻找到extension=php_mbstring.dll,确保扩展被加载——此行首无分号。

下面重点讲使用基本函数substr去实现中文字符串的截取。

1. 基于substr()解决方案

1.1解决思路:

UTF-8编码的字符可能由1-3个字节组成,具体数目可以由第一个字节判断出来。
第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符
第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符,否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号)。

1.2 substr()语法

substr()中文文档
string substr ( string $string , int $start [, int $length ] )

参数

string

输入字符串。必须至少有一个字符。

start

如果 start 是非负数,返回的字符串将从 stringstart 位置开始,从 0 开始计算。
如果 start 是负数,返回的字符串将从 string 结尾处向前数第 start 个字符开始。
如果 string 的长度小于 start ,将返回 FALSE

length

如果提供了正数的 length,返回的字符串将从 start 处开始最多包括 length 个字符(取决于 string 的长度)。
如果提供了负数的 length ,那么 string 末尾处的 length 个字符将会被省略(若 start 是负数则从字符串尾部算起)。
如果 start 不在这段文本中,那么将返回 FALSE
如果提供了值为 0FALSENULLlength,那么将返回一个空字符串。
如果没有提供 length,返回的子字符串将从 start 位置开始直到字符串结尾。

返回值

返回提取的子字符串, 或者在失败时返回 **FALSE
**。

1.3 myGBsubstr()

 function myGBsubstr($string, $start, $length) {
    if (strlen($string) > $length) {
        $str = null;
        $len = 0;
        $i = $start;
        while ( $len < $length) {
        if (ord(substr($string, $i, 1)) > 0xc0) {
            $str .=substr($string, $i, 3);
            $i+= 3;
        }elseif (ord(substr($string, $i, 1)) > 0xa0) {
            $str .= substr($string, $i, 2);
            $i+= 2;
        }else {
            $str.=substr($string, $i, 1);
            $i++;
        }
        $len ++;
        }
        return $str;
    }else {
        return $string;
    }
}

1.4 优化

判断mbstring模块是否可用,如果可用使用原生的mb_substr()函数,反之,使用自己定义的中文字符串截取函数。

function GBsubstr($string, $start,$length) {
    if (!function_exists(mb_substr)) {
        myGBsubstr($string, $start, $length);
    } else {
        mb_substr($string, $start, $length, 'utf8');
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容