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 相关文章推荐
关于mysql 字段的那个点为是定界符
Jan 15 PHP
FCKeditor添加自定义按钮
Mar 27 PHP
PHP面向对象三大特点学习(充分理解抽象、封装、继承、多态)
May 07 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(二)
Jun 23 PHP
php递归法读取目录及文件的方法
Jan 30 PHP
PHP之密码加密的几种方式
Jul 29 PHP
PHP判断表达式中括号是否匹配的简单实例
Oct 22 PHP
CodeIgniter开发实现支付宝接口调用的方法示例
Nov 14 PHP
php自定义时间转换函数示例
Dec 07 PHP
php取出数组单个值的方法
Mar 12 PHP
php提供实现反射的方法和实例代码
Sep 17 PHP
laravel框架邮箱认证实现方法详解
Nov 22 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学习笔记之 函数声明
2011/06/09 PHP
php中文验证码实现示例分享
2014/01/12 PHP
php集成环境xampp中apache无法启动问题解决方案
2014/11/18 PHP
PHP使用token防止表单重复提交的方法
2016/04/07 PHP
PHP基于回溯算法解决n皇后问题的方法示例
2017/11/07 PHP
PHP实现微信支付(jsapi支付)流程步骤详解
2018/03/15 PHP
Some tips of wmi scripting in jscript (1)
2007/04/03 Javascript
一个通过script自定义属性传递配置参数的方法
2014/09/15 Javascript
使用jQuery管理选择结果
2015/01/20 Javascript
node.js 使用ejs模板引擎时后缀换成.html
2015/04/22 Javascript
jQuery实现简单隔行变色的方法
2016/02/20 Javascript
Ajax的概述与实现过程
2016/11/18 Javascript
vue货币过滤器的实现方法
2017/04/01 Javascript
详解vue.js的devtools安装
2017/05/26 Javascript
Angular2 父子组件通信方式的示例
2018/01/29 Javascript
ztree加载完成后显示勾选节点的实现代码
2018/10/22 Javascript
基于vue hash模式微信分享#号的解决
2020/09/07 Javascript
element中Steps步骤条和Tabs标签页关联的解决
2020/12/08 Javascript
用实例详解Python中的Django框架中prefetch_related()函数对数据库查询的优化
2015/04/01 Python
分享一下如何编写高效且优雅的 Python 代码
2017/09/07 Python
python矩阵转换为一维数组的实例
2018/06/05 Python
python生成1行四列全2矩阵的方法
2018/08/04 Python
超简单使用Python换脸实例
2019/03/27 Python
python安装scipy的方法步骤
2019/06/26 Python
把django中admin后台界面的英文修改为中文显示的方法
2019/07/26 Python
Python实现Wordcloud生成词云图的示例
2020/03/30 Python
在python3.64中安装pyinstaller库的方法步骤
2020/06/02 Python
CSS3 animation ? steps 函数详解
2019/08/30 HTML / CSS
Vans英国官方网站:美国南加州的原创极限运动潮牌
2017/01/20 全球购物
英国在线药房和在线药剂师:Chemist 4 U
2020/01/05 全球购物
迪士尼法国在线商店:shopDisney FR
2020/12/03 全球购物
几道数据库的概念性面试题
2014/05/30 面试题
小学生一分钟演讲稿
2014/08/26 职场文书
2019年家电促销广告语集锦
2019/10/21 职场文书
Python基础详解之描述符
2021/04/28 Python
MySQL系列之十三 MySQL的复制
2021/07/02 MySQL