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 相关文章推荐
用Zend Encode编写开发PHP程序
Oct 09 PHP
中篇:安装及配置PHP
Dec 13 PHP
海河写的 Discuz论坛帖子调用js的php代码
Aug 23 PHP
CURL的学习和应用(附多线程实现)
Jun 03 PHP
php实现的常见排序算法汇总
Sep 08 PHP
PHP中使用SimpleXML检查XML文件结构实例
Jan 07 PHP
php递归创建目录的方法
Feb 02 PHP
php操作redis缓存方法分享
Jun 03 PHP
PHP文件与目录操作示例
Dec 24 PHP
PHP中in_array的隐式转换的解决方法
Mar 06 PHP
Laravel 自带的Auth验证登录方法
Sep 30 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
Apr 05 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 printf输出格式使用说明
2010/12/05 PHP
php使用base64加密解密图片示例分享
2014/01/20 PHP
微信自定义菜单的创建/查询/取消php示例代码
2016/08/05 PHP
php写一个函数,实现扫描并打印出自定目录下(含子目录)所有jpg文件名
2017/05/26 PHP
基于Laravel(5.4版本)的基本增删改查操作方法
2019/10/11 PHP
javascript编程起步(第四课)
2007/02/27 Javascript
ASP.NET jQuery 实例4(复制TextBox的文本到本地剪贴板上)
2012/01/13 Javascript
Javascript的数组与字典用法与遍历对象的属性技巧
2012/11/07 Javascript
分析Node.js connect ECONNREFUSED错误
2013/04/09 Javascript
jquery中.add()的使用分析
2013/04/26 Javascript
JavaScript中发布/订阅模式的简单实例
2014/11/05 Javascript
JQuery中模拟image的ajaxPrefilter与ajaxTransport处理
2015/06/19 Javascript
js 声明数组和向数组中添加对象变量的简单实例
2016/07/28 Javascript
仿iframe效果Aajx文件上传实例
2016/11/18 Javascript
JavaScript字符串对象(string)基本用法示例
2017/01/18 Javascript
关于react中组件通信的几种方式详解
2017/12/10 Javascript
vuejs 切换导航条高亮(路由菜单高亮)的方法示例
2018/05/29 Javascript
JavaScript实现仿Clock ISO时钟
2018/06/29 Javascript
JavaScript设计模式之装饰者模式定义与应用示例
2018/07/25 Javascript
详解vue几种主动刷新的方法总结
2019/02/19 Javascript
Mpvue中使用Vant Weapp组件库的方法步骤
2019/05/16 Javascript
js实现QQ邮箱邮件拖拽删除功能
2020/08/27 Javascript
vue操作dom元素的3种方法示例
2020/09/20 Javascript
[58:42]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第一局
2016/02/27 DOTA
python 字符串split的用法分享
2013/03/23 Python
Python基于多线程实现ping扫描功能示例
2018/07/23 Python
Python xlrd excel文件操作代码实例
2020/03/10 Python
Python小整数对象池和字符串intern实例解析
2020/03/21 Python
Python pip 常用命令汇总
2020/10/19 Python
印尼最大的网上书店:Gramedia.com
2018/09/13 全球购物
巴西世界杯32强口号
2014/06/05 职场文书
公司离职证明标准样本
2014/10/05 职场文书
2014年维修工作总结
2014/11/22 职场文书
golang通过递归遍历生成树状结构的操作
2021/04/28 Golang
一文弄懂MySQL索引创建原则
2022/02/28 MySQL
解决xampp安装后Apache无法启动
2022/03/21 Servers