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之Smarty入门
Jan 04 PHP
php 获取可变函数参数的函数
Aug 26 PHP
php 注释规范
Mar 29 PHP
php检测iis环境是否支持htaccess的方法
Feb 18 PHP
PHP中使用TCPDF生成PDF文档实例
Jul 01 PHP
zen_cart实现支付前生成订单的方法
May 06 PHP
PHP学习笔记之php文件操作
Jun 03 PHP
php reset() 函数指针指向数组中的第一个元素并输出实例代码
Nov 21 PHP
简单实现php上传文件功能
Sep 21 PHP
laravel 操作数据库常用函数的返回值方法
Oct 11 PHP
laravel5.1 ajax post 传值_token示例
Oct 24 PHP
Laravel 集成微信用户登录和绑定的实现
Dec 27 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数据结构与算法(PHP描述) 快速排序 quick sort
2012/06/21 PHP
百度地图API应用之获取用户的具体位置
2014/06/10 PHP
PHP正则表达式之捕获组与非捕获组
2015/11/06 PHP
php设计模式之正面模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
javascript call和apply方法
2008/11/24 Javascript
jQuery插件 tabBox实现代码
2010/02/09 Javascript
当鼠标移动到图片上时跟随鼠标显示放大的图片效果
2013/06/06 Javascript
在ASP.NET中使用JavaScript脚本的方法
2013/11/12 Javascript
js与jquery获取父元素,删除子元素的两种不同方法
2014/01/09 Javascript
JavaScript网页定位详解
2014/01/13 Javascript
一个非常全面的javascript URL解析函数和分段URL解析方法
2014/04/12 Javascript
JavaScript的arguments对象应用示例
2014/09/15 Javascript
解决jquery中动态新增的元素节点无法触发事件问题的两种方法
2015/10/30 Javascript
js实现遍历含有input的table实例
2015/12/07 Javascript
Bootstrap自动适应PC、平板、手机的Bootstrap栅格系统
2016/05/27 Javascript
EasyUI创建人员树的实例代码
2017/09/15 Javascript
微信小程序动态增加按钮组件
2018/09/14 Javascript
详解Vue Elementui中的Tag与页面其它元素相互交互的两三事
2018/09/25 Javascript
vue项目中使用Svg的方法
2018/10/24 Javascript
解决layui表格内文本超出隐藏的问题
2019/09/12 Javascript
VUE DEMO之模拟登录个人中心页面之间数据传值实例
2019/10/31 Javascript
python 获取et和excel的版本号
2009/04/09 Python
Python写的创建文件夹自定义函数mkdir()
2014/08/25 Python
Python实现把回车符\r\n转换成\n
2015/04/23 Python
python实现爬虫下载美女图片
2015/07/14 Python
Python的Twisted框架上手前所必须了解的异步编程思想
2016/05/25 Python
使用Python的Turtle绘制哆啦A梦实例
2019/11/21 Python
python 如何设置守护进程
2020/10/29 Python
NFL欧洲商店(德国):NFL Europe Shop DE
2018/11/03 全球购物
新学期决心书
2014/03/11 职场文书
硕士研究生就业推荐信
2014/05/18 职场文书
2014法制宣传日活动总结
2014/07/09 职场文书
信访维稳工作汇报
2014/10/27 职场文书
提升Nginx性能的一些建议
2021/03/31 Servers
启动Tomcat时出现大量乱码的解决方法
2021/06/21 Java/Android
关于CSS浮动与取消浮动的问题
2021/06/28 HTML / CSS