PHP中文字符串截断无乱码解决方法


Posted in PHP onOctober 10, 2016

一个比较好用的字符串截取函数:

function substring($str, $start, $length){ //比较好用字符串截取函数
  $len = $length;
  if($length < 0){
  $str = strrev($str);
  $len = -$length;
  }
  $len= ($len < strlen($str)) ? $len : strlen($str);
  $tmpstr = "";
  for ($i= $start; $i < $len; $i ++)
  {
      if (ord(substr($str, $i, 1)) > 0xa0)
      {
       $tmpstr .= substr($str, $i, 2);
       $i++;
      } else {
       $tmpstr .= substr($str, $i, 1);
      }
  }
  if($length < 0) $tmpstr = strrev($tmpstr);
  return $tmpstr;
}

使用方法示例:

$str1 = '我是一串比较长的中文不带英文';
$str2 = '我是一串比较长的中文带yingwen';


$len = strlen($str1);
echo '<br />'.$len; //return 28

$len = strlen($str2);
echo '<br />'.$len; //return 29

echo '<br />';  
echo substring($str1, 0, 11);  
echo '<br />';
echo substring($str2, 0, 11);    
echo '<br />';
echo substring($str1, 16, 28);  
echo '<br />';
echo substring($str2, 16, 29);

结果显示:

28
29
我是一串比较
我是一串比较
中文不带英文
中文带yingwen

这个函数十分有用,比如用来截断比较长的文件名,但是要在中间加上...,可以这样来做:

function formatName($str, $size){
  $len = strlen($str);
  if(strlen($str) > $size) {
    $part1 = substring($str, 0, $size / 2);
    $part2 = substring($str, $len - ($size/2), $len);
    return $part1 . "..." . $part2;
  } else {
    return $str;
  }
}

另外,网上看到一种超级简单的中文截断解决方案,试用了一下,效果也不错:

echo substr($str1,0,10).chr(0);

原理解释:

chr(0)不是null
07null是什么都没有,而chr(0)的值是0。表示成16进制是0x00,表示成二进制是00000000
08虽然chr(0)不会显示出什么,但是他是一个字符。
09当汉字被截断时,根据编码规则他总是要把后边的其他字符拉过来一起作为汉字解释,这就是出现乱码的原因。而值为0x81到0xff与0x00组合始终都显示为“空”
10根据这一特点,在substr的结果后面补上一个chr(0),就可以防止出现乱码了

----------------------------

20120705更新: 

以上方法虽好,但是偶尔还是会碰到乱码,原因未深究。不过可以用以下的方法,对UTF8字符文本屡试不爽。
注意:该方法中将汉字计算为1单位长度,英文一个字母1单位长度,所以截断时需要注意长度设置。
计算长度的方法:

function strlen_UTF8($str)
{
  $len = strlen($str);
  $n = 0;
  for($i = 0; $i < $len; $i++) {
    $x = substr($str, $i, 1);
    $a = base_convert(ord($x), 10, 2);
    $a = substr('00000000'.$a, -8);
    if (substr($a, 0, 1) == 0) {
    }elseif (substr($a, 0, 3) == 110) {
      $i += 1;
    }elseif (substr($a, 0, 4) == 1110) {
      $i += 2;
    }
    $n++;
  }
  return $n;
} // End strlen_UTF8;

字符串截断函数:

function subString_UTF8($str, $start, $lenth)
  {
    $len = strlen($str);
    $r = array();
    $n = 0;
    $m = 0;
    for($i = 0; $i < $len; $i++) {
      $x = substr($str, $i, 1);
      $a = base_convert(ord($x), 10, 2);
      $a = substr('00000000'.$a, -8);
      if ($n < $start){
        if (substr($a, 0, 1) == 0) {
        }elseif (substr($a, 0, 3) == 110) {
          $i += 1;
        }elseif (substr($a, 0, 4) == 1110) {
          $i += 2;
        }
        $n++;
      }else{
        if (substr($a, 0, 1) == 0) {
          $r[ ] = substr($str, $i, 1);
        }elseif (substr($a, 0, 3) == 110) {
          $r[ ] = substr($str, $i, 2);
          $i += 1;
        }elseif (substr($a, 0, 4) == 1110) {
          $r[ ] = substr($str, $i, 3);
          $i += 2;
        }else{
          $r[ ] = '';
        }
        if (++$m >= $lenth){
          break;
        }
      }
    }
    return join($r);
  } // End subString_UTF8;

使用方法和之前介绍的一样,比如formatName可以实现如下(这对汉字长度做了小优化):

function formatName($str, $size){
 $len = strlen_UTF8($str);
 $one_len = strlen($str);
 $size = $size * 1.5 * $len / ($one_len);
 if(strlen_UTF8($str) > $size) {
  $part1 = subString_UTF8($str, 0, $size / 2);
  $part2 = subString_UTF8($str, $len - ($size/2), $len);
  return $part1 . "..." . $part2;
 } else {
  return $str;
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php中文本数据翻页(留言本翻页)
Oct 09 PHP
PHP中用接口、抽象类、普通基类实现“面向接口编程”与“耦合方法”简述
Mar 23 PHP
基于php设计模式中工厂模式详细介绍
May 15 PHP
phpphp图片采集后按原路径保存图片示例
Feb 18 PHP
CodeIgniter安全相关设置汇总
Jul 03 PHP
PHP中COOKIES使用示例
Jul 26 PHP
PHP读书笔记_运算符详解
Jul 01 PHP
PHP实现自动识别原编码并对字符串进行编码转换的方法
Jul 13 PHP
PHP二维数组去重算法
Dec 17 PHP
PHP实现的常规正则验证helper公共类完整实例
Apr 27 PHP
PHP获取数组中单列值的方法
Jun 10 PHP
详解PHP中mb_strpos的使用
Feb 04 PHP
PHP获取用户客户端真实IP的解决方案
Oct 10 #PHP
php表单加入Token防止重复提交的方法分析
Oct 10 #PHP
Laravel5中防止XSS跨站攻击的方法
Oct 10 #PHP
php中让人头疼的浮点数运算分析
Oct 10 #PHP
Laravel实现自定义错误输出内容的方法
Oct 10 #PHP
PHP定时任务获取微信access_token的方法
Oct 10 #PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
Oct 10 #PHP
You might like
php正则表达式(regar expression)
2011/09/10 PHP
php中apc缓存使用示例
2013/12/25 PHP
php遍历文件夹和文件列表示例分享
2014/03/11 PHP
php警告Creating default object from empty value 问题的解决方法
2014/04/02 PHP
Zend Framework教程之路由功能Zend_Controller_Router详解
2016/03/07 PHP
php实现通过soap调用.Net的WebService asmx文件
2017/02/27 PHP
jquery ui 1.7 ui.tabs 动态添加与关闭(按钮关闭+双击关闭)
2010/04/01 Javascript
JavaScript性能陷阱小结(附实例说明)
2010/12/28 Javascript
JQuery中操作Css样式的方法
2014/02/12 Javascript
jQuery右侧选项卡焦点图片轮播特效代码分享
2015/09/05 Javascript
jQuery实现右侧显示可向左滑动展示的深色QQ客服效果代码
2015/10/23 Javascript
从重置input file标签中看jQuery的 .val() 和 .attr(“value”) 区别
2016/06/12 Javascript
jQuery在header中设置请求信息的方法
2017/03/06 Javascript
详解nodejs微信jssdk后端接口
2017/05/25 NodeJs
使用vue2实现带地区编号和名称的省市县三级联动效果
2018/11/05 Javascript
layer关闭弹出窗口触发表单提交问题的处理方法
2019/09/25 Javascript
Python splitlines使用技巧
2008/09/06 Python
pyqt4教程之widget使用示例分享
2014/03/07 Python
对pandas replace函数的使用方法小结
2018/05/18 Python
Python字典创建 遍历 添加等实用基础操作技巧
2018/09/13 Python
如何通过python的fabric包完成代码上传部署
2019/07/29 Python
python Pandas如何对数据集随机抽样
2019/07/29 Python
Python3实现mysql连接和数据框的形成(实例代码)
2020/01/17 Python
屏蔽Django admin界面添加按钮的操作
2020/03/11 Python
CSS3实现多背景展示效果通过CSS3定位多张背景
2014/08/10 HTML / CSS
HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题
2021/01/19 HTML / CSS
FC-Moto英国:欧洲最大的摩托车服装和头盔商店之一
2019/08/25 全球购物
法国春天百货官网:Printemps.com
2020/06/29 全球购物
会计电算化应届生求职信
2013/11/03 职场文书
幼儿园庆六一游园活动方案
2014/01/29 职场文书
期末自我鉴定
2014/02/02 职场文书
公务员平时考核实施方案
2014/03/11 职场文书
幼儿园学前班幼儿评语
2014/12/29 职场文书
2015年酒店客房部工作总结
2015/04/25 职场文书
高中语文教材(文学文化常识大全一)
2019/08/13 职场文书
laravel ajax curd 搜索登录判断功能的实现
2021/04/17 PHP