高效的中文字符串截取函数

原创 2003年08月18日 10:31:00

高效的中文字符串截取函数
作者:徐祖宁

在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

截取字符串,含有汉字和字母,不能截半个汉字

/** * 2017年6月19日 * * 问题描述: * 编写一个截取字符串的函数,输入为一个字符串和字节数, * 输出为按字节截取的字符串。但是要保证汉字不被截半...
  • DREAMEER_DD
  • DREAMEER_DD
  • 2017年06月19日 10:39
  • 694

thinkphp 模板截取中文字符串函数

项目开发中,常常会遇到中文字符串截取问题,例如新闻标题太长需要用“...”代替 //函数解释: //msubstr($str, $start=0, $length, $charset=”utf-8″,...
  • hdxyzlh_0225
  • hdxyzlh_0225
  • 2016年07月07日 15:17
  • 1121

lua 含中文的字符串处理--分离字符、计算字符数、截取指定长度

lua中对中文字符串的一些处理 分离字符 将每个字符分离出来,放到table中,一个单元内一个字符 function StringToTable(s) local tb = {} ...
  • a102111
  • a102111
  • 2016年08月12日 20:18
  • 3739

Java中文字符串截取,不能返回半个汉字

Java中文字符串截取,不能返回半个汉字
  • loongshawn
  • loongshawn
  • 2017年03月15日 09:56
  • 1279

提C#中截取长度中文字符串

6 后记helperm, , aux换言之,如1236官网的证书Anr定位到的相应的关键信息.8,1如上算法所述根据变参数的不同,插件化我们可以在log量的时间内查找和调整移动e.printStack...
  • jianningsun1879
  • jianningsun1879
  • 2017年01月26日 20:26
  • 272

如何解决用substr()函数对中文字符串截取时的乱码

在PHP程序开发中,经常会执行字符串的截取操作,比如输出信息列表时,标题不宜过长,打印文章摘要时,也要执行一系列的字符串截取操作。遇到这些需求时,我们经常会想到使用substr()方法来实现,subs...
  • luyaran
  • luyaran
  • 2016年10月24日 19:37
  • 2921

Cocos2dx中英文混合字符串截取

Cocos2dx中英文混合字符串截取方法
  • u013058216
  • u013058216
  • 2016年11月22日 18:45
  • 924

从一个包含汉字和其他字符的字符串中截取指定字节长度的字符串,不可以出现中文乱码

最近整理之前自己学习Java时的一些代码笔记,可能都是一些比较基础的Java知识,在这里只是给需要的人参考一下。 要求描述:从一个包含汉字和其他字符的字符串中截取指定字节长度的字符串,不可以出现中文...
  • shallynever
  • shallynever
  • 2016年07月30日 13:44
  • 1035

java按字节截取带有汉字的字符串的解法

由于接口使用的oracle字段长度为固定字节数,然后传进来的字符串估计比数据库字段的总字节数要大,那么截取小于数据库字节数的字符串。 自己参考网上的例子,整了个递归调用就可以了public stati...
  • cuker919
  • cuker919
  • 2013年12月12日 13:47
  • 30118

Java按字节数截取字符串(防止中文被截成一半)

Web应用程序在浏览器中显示字符串时,由于显示长度的限制,常常需要将字符串截取后再进行显示。 但目前很多流行的语言,如C#、Java内部采用的都是 Unicode 16(UCS2)编码,在这种编码中...
  • u013409622
  • u013409622
  • 2015年04月22日 14:34
  • 2016
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:高效的中文字符串截取函数
举报原因:
原因补充:

(最多只允许输入30个字)