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 相关文章推荐
在Zeus Web Server中安装PHP语言支持
Oct 09 PHP
用PHP和ACCESS写聊天室(十)
Oct 09 PHP
Search File Contents PHP 搜索目录文本内容的代码
Feb 21 PHP
PHP 抓取网页图片并且另存为的实现代码
Mar 24 PHP
使用PHP函数scandir排除特定目录
Jun 12 PHP
php随机获取金山词霸每日一句的方法
Jul 09 PHP
CodeIgniter配置之config.php用法实例分析
Jan 19 PHP
PHP动态生成指定大小随机图片的方法
Mar 25 PHP
php使用自定义函数实现汉字分割替换功能示例
Jan 30 PHP
PHP框架laravel的.env文件配置教程
Jun 07 PHP
Laravel框架Blade模板简介及模板继承用法分析
Dec 03 PHP
laravel添加角色和模糊搜索功能的实现代码
Jun 22 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 图像处理类1
2009/06/15 PHP
PHP模块 Memcached功能多于Memcache
2011/06/14 PHP
JavaScript创建命名空间的5种写法
2014/06/24 PHP
PHP中file_get_contents高?用法实例
2014/09/24 PHP
codeigniter显示所有脚本执行时间的方法
2015/03/21 PHP
PHP基于PDO调用sqlserver存储过程通用方法【基于Yii框架】
2017/10/07 PHP
javascript游戏开发之《三国志曹操传》零部件开发(一)让静态人物动起来
2013/01/23 Javascript
jQuery UI 实现email输入提示实例
2013/08/15 Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
2014/03/05 Javascript
Node.js实现在目录中查找某个字符串及所在文件
2014/09/03 Javascript
jQuery实现下滑菜单导航效果代码
2015/08/25 Javascript
详解webpack 多入口配置
2017/06/16 Javascript
Angular实现响应式表单
2017/08/04 Javascript
checkbox:click事件触发span元素内容改变的方法
2017/09/11 Javascript
JavaScript数据结构与算法之二叉树实现查找最小值、最大值、给定值算法示例
2019/03/01 Javascript
详解vue-cli3多环境打包配置
2019/03/28 Javascript
vue.js中使用微信扫一扫解决invalid signature问题(完美解决)
2020/04/11 Javascript
three.js 将图片马赛克化的示例代码
2020/07/31 Javascript
[08:08]2014DOTA2国际邀请赛中国区预选赛精彩TOPPLAY
2014/06/25 DOTA
[38:23]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第二场 11.01
2020/11/02 DOTA
在Python中使用base64模块处理字符编码的教程
2015/04/28 Python
Python在Console下显示文本进度条的方法
2016/02/14 Python
python基础教程之分支、循环简单用法
2016/06/16 Python
Python wxPython库消息对话框MessageDialog用法示例
2018/09/03 Python
python中import与from方法总结(推荐)
2019/03/21 Python
python如何操作mysql
2020/08/17 Python
Python-openpyxl表格读取写入的案例详解
2020/11/02 Python
jurlique茱莉蔻英国官网:澳洲天然护肤品
2018/08/03 全球购物
音乐幼师求职信
2014/07/09 职场文书
关于旅游的活动方案
2014/08/15 职场文书
捐书倡议书
2014/08/29 职场文书
公司感恩节活动策划书
2014/10/11 职场文书
合法的离婚协议书范本
2014/10/23 职场文书
个人创业事迹材料
2014/12/30 职场文书
幼儿园重阳节活动总结
2015/05/05 职场文书
用CSS3画一个爱心
2021/04/27 HTML / CSS