在php中使用传统的字符串截取函数substr处理含有中文字符的字符串时会出现汉字被切断的现象。当可以使用php扩展库时,我们可以用mb_substr代替。但是该扩展库在连接时有一定的困难——linux下需重新编译php,有时并不能可做到,更何况其冗余函数较多。 在网络上可以看到很多实现此功能的函数。但算法多是循环判断,当字符串较大时效率极低。 为此这里介绍两个高效的函数:c_substr、m_substr。他们的用法完全与substr和mb_substr相同。不同之处在于:c_substr按字节计算,即一个汉字的长度为2;m_substr按字计算,即一个汉字的长度为1。可根据需要选用。 function c_substr($str,$start=0) { $ch = chr(127); $p = array("/[\x81-\xfe]([\x81-\xfe]|[\x40-\xfe])/","/[\x01-\x77]/"); $r = array("",""); if(func_num_args() > 2) $end = func_get_arg(2); else $end = strlen($str); if($start < 0) $start += $end; if($start > 0) { $s = substr($str,0,$start); if($s[strlen($s)-1] > $ch) { $s = preg_replace($p,$r,$s); $start += strlen($s); } } $s = substr($str,$start,$end); $end = strlen($s); if($s[$end-1] > $ch) { $s = preg_replace($p,$r,$s); $end += strlen($s); } return substr($str,$start,$end); } function m_substr($str,$start) { preg_match_all("/[\x80-\xff]?./",$str,$ar); if(func_num_args() >= 3) { $end = func_get_arg(2); return join("",array_slice($ar[0],$start,$end)); }else return join("",array_slice($ar[0],$start)); } 性能测试: 1、使用pear的Benchmark_Iterate类作为计时器 2、以循环判断的对照函数 function TrimChinese($str,$len){ $r_str=""; $i=0; while ($i<$len){ $ch=substr($str,$i,1); if(ord($ch)>0x80) $i++; $i++; } $r_str=substr($str,0,$i); return $r_str; } 3、测试环境:p2/166、nt4 iis4+php4.3.1 4、测试代码: require_once "Benchmark/Iterate.php"; $benchmark = new Benchmark_Iterate; $benchmark->run(100, "TrimChinese", $str , 1000); $result = $benchmark->get(); echo "TrimChinese:".$result[mean]."<br>"; $benchmark->run(100, "c_substr", $str , 3,1000); $result = $benchmark->get(); echo "c_substr:".$result[mean]."<br>"; $benchmark->run(100, "m_substr", $str , 3,1000); $result = $benchmark->get(); echo "m_substr:".$result[mean]."<br>"; $benchmark->run(100, "mb_substr", $str , 3,1000); $result = $benchmark->get(); echo "mb_substr:".$result[mean]."<br>"; 5、测试文字:本文 6、测试结果:(秒) TrimChinese:0.058972 c_substr:0.000809 m_substr:0.000666 mb_substr:0.000458
|