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 相关文章推荐
Windows下PHP5和Apache的安装与配置
Sep 05 PHP
URL Rewrite的设置方法
Jan 02 PHP
php下判断数组中是否存在相同的值array_unique
Mar 25 PHP
php adodb连接不同数据库
Mar 19 PHP
PHP session有效期session.gc_maxlifetime
Apr 20 PHP
php float不四舍五入截取浮点型字符串方法总结
Oct 28 PHP
实用的PHP带公钥加密类分享(每次加密结果都不一样哦)
Aug 20 PHP
php按字符无乱码截取中文的方法
Mar 27 PHP
PHP如何实现跨域
May 30 PHP
Yii2使用自带的UploadedFile实现的文件上传
Jun 20 PHP
php注册系统和使用Xajax即时验证用户名是否被占用
Aug 31 PHP
php集成开发环境详解
Sep 24 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
德劲1107的电路分析与打磨
2021/03/02 无线电
phpMyAdmin链接MySql错误 个人解决方案
2009/12/28 PHP
一个PHP缓存类代码(附详细说明)
2011/06/09 PHP
PHP批量上传图片的具体实现方法介绍.
2014/02/26 PHP
数据结构之利用PHP实现二分搜索树
2020/10/25 PHP
jQuery 表单验证扩展(三)
2010/10/20 Javascript
javascript实现信息的显示和隐藏如注册页面
2013/12/03 Javascript
js鼠标及对象坐标控制属性详细解析
2013/12/14 Javascript
jQuery实现的原图对比窗帘效果
2014/06/15 Javascript
javascript实现简单的html5视频播放器
2015/05/06 Javascript
js判断用户是输入的地址请求的路径(实例讲解)
2017/07/18 Javascript
基于vue的短信验证码倒计时demo
2017/09/13 Javascript
jquery实现左右轮播切换效果
2018/01/01 jQuery
react native 获取地理位置的方法示例
2018/08/28 Javascript
自己动手封装一个React Native多级联动
2018/09/19 Javascript
vue slot与传参实例代码讲解
2019/04/28 Javascript
Python对小数进行除法运算的正确方法示例
2014/08/25 Python
Python里disconnect UDP套接字的方法
2015/04/23 Python
详解Django中的form库的使用
2015/07/18 Python
Python使用Pickle模块进行数据保存和读取的讲解
2019/04/09 Python
Python内置类型性能分析过程实例
2020/01/29 Python
Python函数基本使用原理详解
2020/03/19 Python
Django import export实现数据库导入导出方式
2020/04/03 Python
Python爬虫:Request Payload和Form Data的简单区别说明
2020/04/30 Python
Python基于template实现字符串替换
2020/11/27 Python
沙特阿拉伯电子产品和家用电器购物网站:Black Box
2019/07/24 全球购物
如何判断计算机可能已经中马
2013/03/22 面试题
一套中级Java程序员笔试题
2015/01/14 面试题
会计电算化专业毕业生自荐信
2013/12/20 职场文书
企业文明单位申报材料
2014/05/16 职场文书
2014年九一八事变演讲稿
2014/09/14 职场文书
导游词之云南丽江古城
2019/09/17 职场文书
详解非极大值抑制算法之Python实现
2021/06/28 Python
Python办公自动化解决world文件批量转换
2021/09/15 Python
解决IIS7下无法绑定https主机的问题
2022/04/29 Servers
SpringBoot前端后端分离之Nginx服务器下载安装过程
2022/08/14 Servers