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 相关文章推荐
支持oicq头像的留言簿(二)
Oct 09 PHP
JS 网站性能优化笔记
May 24 PHP
php和mysql中uft-8中文编码乱码的几种解决办法
Apr 19 PHP
php面向对象 字段的声明与使用
Jun 14 PHP
PHP统计目录大小的自定义函数分享
Nov 18 PHP
PHP.vs.JAVA
Apr 29 PHP
Smarty高级应用之缓存操作技巧分析
May 14 PHP
PHP自定义函数获取URL中一级域名的方法
Aug 23 PHP
php基于单例模式封装mysql类完整实例
Oct 18 PHP
PHP读取文件的常见几种方法
Nov 03 PHP
修改Laravel自带的认证系统的User类的命名空间的步骤
Oct 15 PHP
详解PHP中的8个魔术常量
Jul 06 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
上海无线电三厂简史修改版
2021/03/01 无线电
PHP中的CMS的涵义
2007/03/11 PHP
用来给图片加水印的PHP类
2008/04/09 PHP
用PHP调用Oracle存储过程的方法
2008/09/12 PHP
php处理单文件、多文件上传代码分享
2016/08/24 PHP
JavaScript Event学习第十一章 按键的检测
2010/02/10 Javascript
json-lib出现There is a cycle in the hierarchy解决办法
2010/02/24 Javascript
web页面数据展示新想法(json)
2010/06/08 Javascript
编写自己的jQuery插件简单实现代码
2011/04/19 Javascript
自己动手开发jQuery插件教程
2011/08/25 Javascript
深入理解Javascript中this的作用域
2014/08/12 Javascript
基于NodeJS的前后端分离的思考与实践(二)模版探索
2014/09/26 NodeJs
分离与继承的思想实现图片上传后的预览功能:ImageUploadView
2016/04/07 Javascript
针对BootStrap中tabs控件的美化和完善(推荐)
2016/07/06 Javascript
jQuery 翻页组件yunm.pager.js实现div局部刷新的思路
2016/08/11 Javascript
Vue.js快速入门教程
2016/09/07 Javascript
weUI应用之JS常用信息提示弹层的封装
2016/11/21 Javascript
js CSS3实现卡牌旋转切换效果
2017/07/04 Javascript
Kindeditor单独调用多图上传实例
2017/07/31 Javascript
webpack中的热刷新与热加载的区别
2018/04/09 Javascript
vue props对象validator自定义函数实例
2019/11/13 Javascript
微信小程序wx.navigateTo方法里的events参数使用详情及场景
2020/01/07 Javascript
在Django中编写模版节点及注册标签的方法
2015/07/20 Python
python安装cx_Oracle模块常见问题与解决方法
2017/02/21 Python
Python爬虫实例_城市公交网络站点数据的爬取方法
2018/01/10 Python
python3安装pip3(install pip3 for python 3.x)
2018/04/03 Python
python3爬虫之设计签名小程序
2018/06/19 Python
浅述python中深浅拷贝原理
2018/09/18 Python
Python日期时间Time模块实例详解
2019/04/15 Python
python如何获取列表中每个元素的下标位置
2019/07/01 Python
Python 实现自动导入缺失的库
2019/10/29 Python
pytorch进行上采样的种类实例
2020/02/18 Python
html5版canvas自由拼图实例
2014/10/15 HTML / CSS
Trip.com澳大利亚:在线旅行社
2019/12/01 全球购物
工会趣味活动方案
2014/08/18 职场文书
el-table-column 内容不自动换行的解决方法
2022/08/14 Vue.js