5
回答
PHP截取字符串(UTF_8)方法, 求高手分析~
注册华为云得mate10,2.9折抢先购!>>>   

PHP语言: 求对于这个函数的分析  

小弟学艺不精, 努力分析, 查手册, 奈何仍然不懂, 故发布出来, 望高手不吝赐教~

^_^    希望可以给此函数添加上注释 和 分析的思路~

注: 此函数可能并不十分正确.

 

 

	function truncate_utf8_string($string, $length, $etc = '...')
	{
	    $result = '';
	    $string = html_entity_decode(trim(strip_tags($string)), ENT_QUOTES, 'UTF-8');
	    $strlen = strlen($string);
	    for ($i = 0; (($i < $strlen) && ($length > 0)); $i++)
	    {
			if ($number = strpos(str_pad(decbin(ord(substr($string, $i, 1))), 8, '0', STR_PAD_LEFT), '0'))
			{
			    if ($length < 1.0)
		        {
					break;
			    }
			    $result .= substr($string, $i, $number);
			    $length -= 1.0;
			    $i += $number - 1;
			}
			else
			{
			    $result .= substr($string, $i, 1);
			    $length -= 0.5;
			}
	    }
	    $result = htmlspecialchars($result, ENT_QUOTES, 'UTF-8');
	    if ($i < $strlen)
	    {
		    $result .= $etc;
	    }
	    return $result;
	}

举报
斯文剑客
发帖于6年前 5回/1K+阅
共有5个答案 最后回答: 5年前
php文件编码必须是utf-8才能正确执行

 

$string = 'PHP 有很方便的 function 让你可以直接达到此功能.';
$len = 11;
$string = strip_tags($string);
$string = mb_strimwidth($string, 0, $len, '...Read More', 'UTF-8');
echo $string . "<br />\r\n";

使用了mb_string扩展中的特有函数,此方法中文字的长度是2,并且自动留出了余量,mb_strwidth 是计算字的宽度。

--- 共有 4 条评论 ---
斯文剑客@maxmas : 3Q 6年前 回复
maxmas你可以參考 http://blog.wu-boy.com/2011/02/%E5%88%A9%E7%94%A8-mb_strwidth-%E5%8F%96%E4%BB%A3-mb_strlen-%E8%A8%88%E7%AE%97-multi-byte-%E5%AD%97%E6%95%B8/# 6年前 回复
maxmas@LiuHui1990 : 應該說一個字佔用幾個字元,這樣你比較好理解,英文是一個字元,一個中文字則是二個字元,不同含數計算方式不一樣,而mb_strwidth會將中文字算成二字元,英文及符號則是一個字元,因此就不會發生切到中文字的問題 6年前 回复
斯文剑客我知道字符串的长度这个概念 ( 比如: strlen(), mb_strlen() ), 但是字符串宽度怎么理解? 6年前 回复

我在网上搜集了一下, 包含着楼上和搂主的, 共3中:

注: 我觉得第2种方式比较好, 因为 第1种 和 第3种的截取方式我不太理解为什么这么截取, 而第2种是实实在在的截取了 10 个字符(包括汉字)

代码(包括测试)如下:

<?php
header('Content-Type: text/html; charset=utf-8');
echo '<pre>';
var_dump(mb_strwidth( '...', 'UTF-8'));//字符串 '...' 的长度

//01 测试
$string = '<br/>PHP ,有很方便的 function 让你可以直接达到此功能.';
$string = strip_tags($string);
$string = mb_strimwidth($string, 0, 10, '...', 'UTF-8');

var_dump( $string );
var_dump(mb_strwidth($string, 'UTF-8'));
var_dump(mb_strlen($string, 'UTF-8'));

echo '<hr>';

//02 测试
$string = '<br/>PHP ,有很方便的 function 让你可以直接达到此功能.';

$string = strip_tags($string);
var_dump(cut_str($string, 10));
var_dump(mb_strlen(cut_str($string, 10), 'UTF-8'));
var_dump(mb_strwidth(cut_str($string, 10), 'UTF-8'));

echo '<hr>';

//03 测试
$string = '<br/>PHP ,有很方便的 function 让你可以直接达到此功能.';
var_dump(truncate_utf8_string($string, 10));
var_dump(mb_strlen(truncate_utf8_string($string, 10), 'UTF-8'));
var_dump(mb_strwidth(truncate_utf8_string($string, 10), 'UTF-8'));




function cut_str($sourcestr, $cutlength) {
    $returnstr = '';
    $i = 0;
    $n = 0;
    $str_length = strlen($sourcestr); //字符串的字节数
    while (($n < $cutlength) and ($i <= $str_length)) {
        $temp_str = substr($sourcestr, $i, 1);
        $ascnum = Ord($temp_str);   //得到字符串中第$i位字符的ascii码
        if ($ascnum >= 224) {       //如果ASCII位高与224,
            $returnstr = $returnstr . substr($sourcestr, $i, 3); //根据UTF-8编码规范,将3个连续的字符计为单个字符
            $i = $i + 3;            //实际Byte计为3
            $n++;                   //字串长度计1
        } elseif ($ascnum >= 192) { //如果ASCII位高与192,
            $returnstr = $returnstr . substr($sourcestr, $i, 2); //根据UTF-8编码规范,将2个连续的字符计为单个字符
            $i = $i + 2;            //实际Byte计为2
            $n++;                   //字串长度计1
        } elseif ($ascnum >= 65 && $ascnum <= 90) { //如果是大写字母,
            $returnstr = $returnstr . substr($sourcestr, $i, 1);
            $i = $i + 1;            //实际的Byte数仍计1个
            $n++;                   //但考虑整体美观,大写字母计成一个高位字符
        } else {                    //其他情况下,包括小写字母和半角标点符号,
            $returnstr = $returnstr . substr($sourcestr, $i, 1);
            $i = $i + 1;            //实际的Byte数计1个
            $n = $n + 0.5;          //小写字母和半角标点等与半个高位字符宽…
        }
    }
    if ($str_length > $cutlength) {
        $returnstr = $returnstr .'...'; //超过长度时在尾处加上省略号
    }
    return $returnstr;
}



function truncate_utf8_string($string, $length, $etc = '...') {
    $result = '';
    $string = html_entity_decode(trim(strip_tags($string)), ENT_QUOTES, 'UTF-8');
    $strlen = strlen($string);
    for ($i = 0; (($i < $strlen) && ($length > 0)); $i++) {
        if ($number = strpos(str_pad(decbin(ord(substr($string, $i, 1))), 8, '0', STR_PAD_LEFT), '0')) {
            if ($length < 1.0) {
                break;
            }
            $result .= substr($string, $i, $number);
            $length -= 1.0;
            $i += $number - 1;
        } else {
            $result .= substr($string, $i, 1);
            $length -= 0.5; // Question Here.
        }
    }
    $result = htmlspecialchars($result, ENT_QUOTES, 'UTF-8');
    if ($i < $strlen) {
        $result .= $etc;
    }
    return $result;
}

Result:

function utf8Substr($str, $from, $len) {
        return preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,' 
. $from . '}' . '((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'
 . $len . '}).*#s', '$1', $str);
    }

--- 共有 1 条评论 ---
斯文剑客这种方式非常简洁哟, 如果我要跳过空格截取呢, 比如说有一个字符串 '我 爱中华人民共和国', 我截取3个字, 那么结果应该是: '我 爱中', 跳过空格截取哟~ utf8Substr()应该与mb_substr($string, $start, $length, 'UTF-8')这个函数功能一样吧~ 6年前 回复
function utf8Substr($str, $from, $len) {
        return preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,' . $from . '}' . '((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,' . $len . '}).*#s', '$1', $str);
    }
顶部