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生成HTML静态页面实例代码
Aug 31 PHP
php颜色转换函数hex-rgb(将十六进制格式转成十进制格式)
Sep 23 PHP
windwos下使用php连接oracle数据库的过程分享
May 26 PHP
优化WordPress中文章与评论的时间显示
Jan 12 PHP
CodeIgniter配置之config.php用法实例分析
Jan 19 PHP
php运行报错Call to undefined function curl_init()的最新解决方法
Nov 20 PHP
PHP实现简单ajax Loading加载功能示例
Dec 28 PHP
基于win2003虚拟机中apache服务器的访问
Aug 01 PHP
PHP实现一个轻量级容器的方法
Jan 28 PHP
Laravel框架实现多数据库连接操作详解
Jul 12 PHP
Thinkphp5.0 框架使用模型Model添加、更新、删除数据操作详解
Oct 11 PHP
PHP替换Word中变量并导出PDF图片的实现方法
Nov 26 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
实用函数4
2007/11/08 PHP
PHP程序员常见的40个陋习,你中了几个?
2014/11/20 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
2015/10/19 PHP
Swoole-1.7.22 版本已发布,修复PHP7相关问题
2015/12/31 PHP
PHP用函数嵌入网站访问量计数器
2017/10/27 PHP
用jQuery简化JavaScript开发分析
2009/02/19 Javascript
在js(jquery)中获得文本框焦点和失去焦点的方法
2012/12/04 Javascript
jquery实现的网页自动播放声音
2014/04/30 Javascript
javascript控制在光标位置插入文字适合表情的插入
2014/06/09 Javascript
js运动动画的八个知识点
2015/03/12 Javascript
javascript学习总结之js使用技巧
2015/09/02 Javascript
JS结合bootstrap实现基本的增删改查功能
2016/07/22 Javascript
Javascript循环删除数组中元素的几种方法示例
2017/05/18 Javascript
浅谈ES6 模板字符串的具体使用方法
2017/11/07 Javascript
vue、react等单页面项目应该这样子部署到服务器
2018/01/03 Javascript
关于express与koa的使用对比详解
2018/01/25 Javascript
ES6知识点整理之函数对象参数默认值及其解构应用示例
2019/04/17 Javascript
Vuex的API文档说明详解
2020/02/05 Javascript
[02:56]DOTA2亚洲邀请赛 VG出场战队巡礼
2015/02/07 DOTA
利用python爬取斗鱼app中照片方法实例
2017/12/03 Python
python 堆和优先队列的使用详解
2019/03/05 Python
详解Python locals()的陷阱
2019/03/26 Python
Python实现使用request模块下载图片demo示例
2019/05/24 Python
Python的几种主动结束程序方式
2019/11/22 Python
解决Keras TensorFlow 混编中 trainable=False设置无效问题
2020/06/28 Python
Python __slots__的使用方法
2020/11/15 Python
Html5 webview元素定位工具的实现
2020/08/07 HTML / CSS
澳大利亚领先的睡衣品牌:Peter Alexander
2016/08/16 全球购物
意大利运动服减价商店:ScontoSport
2020/03/10 全球购物
荷兰DOD药房中文官网:DeOnlineDrogist
2020/12/27 全球购物
什么是反射
2012/03/17 面试题
系统管理员的职责包括那些?管理的对象是什么?
2016/09/20 面试题
宣传工作经验材料
2014/06/02 职场文书
酒店辞职信怎么写
2015/02/27 职场文书
经理聘任证明
2015/03/02 职场文书
shell进度条追踪指令执行时间的场景分析
2022/06/16 Servers