PHP中使用substr()截取字符串出现中文乱码问题该怎么办


Posted in PHP onOctober 21, 2015

在PHP程序开发中,经常会执行字符串的截取操作,比如输出信息列表时,标题不宜过长,打印文章摘要时,也要执行一系列的字符串截取操作。遇到这些需求时,我们经常会想到使用substr()方法来实现,substr()对全英文字符串的截取是比较适合的。

但字符串只要出现中文字符,就有可能导致PHP substr中文乱码,因为中文UTF-8编码,每个汉字占3字节,而GB2312占2字节,英文占1字节,截取位数不准确,substr()硬生生地将一个中文字符“锯”成两半,造成断开的字符会把其后的..拉过来一起做一个字,所以出现了PHP substr中文乱码。

substr --- 取得部份字符串

语法 : string substr (string string, int start [, int length])

说明 :

substr( )传回 string的一部份字符串,由参数 start和 length指定。

如果 start是正数,传回的字符串将会从 string的第 start个字元开始。

Example :

<?php
$rest = substr ("abcdef", 1); // returns "bcdef"
$rest = substr ("abcdef", 1, 3); // returns "bcd"
?>

如果 start是负数,传回的字符串将会从 string结尾的第 start个字开始。

Example :

<?php
$rest = substr ("abcdef", -1); // returns "f"
$rest = substr ("abcdef", -2); // returns "ef"
$rest = substr ("abcdef", -3, 1); // returns "d"
?>

如果有给予参数 length而且是正数时,传回的字符串将会从 start传回 length个字元。
如果有给予参数 length而且是负数时,传回的字符串将会结束于 string结尾的第 length个字元。

Example :

<?php
$rest = substr ("abcdef", 1, -1); // returns "bcde"
?>

对于英文没有问题,我们测试一个中文

<?php
$rest = substr ("中国人", 1, -1); // returns "fdsafsda" 就是乱码了
?>

这种截取字符的结果,肯定不是我们想要的结果,这种出现PHP substr中文乱码的情况,可能会导致程序无法正常运行。解决办法主要有两种:

一、使用mbstring扩展库的mb_substr()截取就不会出现乱码了。

可以用mb_substr()/mb_strcut()这个函数,mb_substr()/mb_strcut()的用法与substr()相似,只是在mb_substr()/mb_strcut最后要加入多一个参数,以设定字符串的编码,但是一般的服务器都没打开php_mbstring.dll,需要在php.ini在把php_mbstring.dll打开。

<?php
  echo mb_substr("php中文字符encode",0,4,"utf-8");
?>

如果未指定最后一个编码参数,会是三个字节为一个中文,这就是utf-8编码的特点,若加上utf-8字符集说明,所以,是以一个字为单位来截取的。

使用的时候要注意php文件的编码,和网页显示时的编码。使用这个mb_substr方法要事先知道字符串的编码,如果不知道编码,就需要判断,mbstring库还提供了mb_check_encoding来检验字符串编码,但还不完善。

PHP 自带几种字符串截取函数,其中常用到的就是 substr 和 mb_substr。前者在处理中文时,GBK 为 2 个长度单位,UTF 为 3 个长度单位,后者指定编码后,一个中文即为 1 个长度单位。

substr 有时会截 1/3 个中文或半个中文,会显示乱码,相对来说 mb_substr 更适合我们使用。不过有时候 mb_substr 就显得不那么好用了。例如我要显示一个小图片的简要信息,5 个中文正好,超过 5 个就截取前4再加上 ”…”,这样处理中文是没问题了,可是处理英文或数字,这样截取就太短了。

二、自己书写截取函数,但效率不如用mbstring扩展库来得高。下面是ecshop里面的截取UTF-8编码下字符串的函数。

function sub_str($str, $length = , $append = true)
{
  $str = trim($str);
  $strlength = strlen($str);
  if ($length == || $length >= $strlength)
  {
    return $str; //截取长度等于或大于等于本字符串的长度,返回字符串本身
  }
  elseif ($length < ) //如果截取长度为负数
  {
    $length = $strlength + $length;//那么截取长度就等于字符串长度减去截取长度
    if ($length < )
    {
      $length = $strlength;//如果截取长度的绝对值大于字符串本身长度,则截取长度取字符串本身的长度
    }
  }
  if (function_exists('mb_substr'))
  {
    $newstr = mb_substr($str, , $length, EC_CHARSET);
  }
  elseif (function_exists('iconv_substr'))
  {
    $newstr = iconv_substr($str, , $length, EC_CHARSET);
  }
  else
  {
    //$newstr = trim_right(substr($str, , $length));
    $newstr = substr($str, , $length);
  }
  if ($append && $str != $newstr)
  {
    $newstr .= '...';
  }
  return $newstr;
}

好了,本文全部叙述到此为止,相信会给大家带来收获的,以上代码也很简单,有不明白的地方欢迎给我留言,我会在第一时间给大家答复的。

PHP 相关文章推荐
给初学者的30条PHP最佳实践(荒野无灯)
Aug 02 PHP
PHP实现链式操作的核心思想
Jun 23 PHP
Yii2 GridView实现列表页直接修改数据的方法
May 16 PHP
谈谈PHP连接Access数据库的注意事项
Aug 12 PHP
php中的抽象方法和抽象类
Feb 14 PHP
浅谈Yii乐观锁的使用及原理
Jul 25 PHP
PHP两个n位的二进制整数相加问题的解决
Aug 26 PHP
PHP实现websocket通信的方法示例
Aug 28 PHP
ThinkPHP中获取指定日期后工作日的具体日期方法
Oct 14 PHP
thinkPHP框架中layer.js的封装与使用方法示例
Jan 18 PHP
ThinkPHP5与单元测试PHPUnit使用详解
Feb 23 PHP
详解使用php-cs-fixer格式化代码
Sep 16 PHP
PHP中的switch语句的用法实例详解
Oct 21 #PHP
PHP 实现的将图片转换为TXT
Oct 21 #PHP
PHP实现清除wordpress里恶意代码
Oct 21 #PHP
表单提交错误后返回内容消失问题的解决方法(PHP网站)
Oct 20 #PHP
php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
Oct 20 #PHP
PHP页面转UTF-8中文编码乱码的解决办法
Oct 20 #PHP
php限制文件下载速度的代码
Oct 20 #PHP
You might like
linux下使用ThinkPHP需要注意大小写导致的问题
2011/08/02 PHP
ExtJS扩展 垂直tabLayout实现代码
2009/06/21 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
js给页面加style无效果的解决方法
2014/01/20 Javascript
基于javascript实现窗口抖动效果
2016/01/03 Javascript
基于JS实现Android,iOS一个手势动画效果
2016/04/27 Javascript
仿Angular Bootstrap TimePicker创建分钟数-秒数的输入控件
2016/07/01 Javascript
DropDownList实现可输入可选择(两种版本可选)
2016/12/07 Javascript
JavaScript中的 attribute 和 jQuery中的 attr 方法浅析
2017/01/04 Javascript
BootStrap CSS全局样式和表格样式源码解析
2017/01/20 Javascript
Vue指令的钩子函数使用方法
2017/03/20 Javascript
详解Angular2中Input和Output用法及示例
2017/05/21 Javascript
vue用addRoutes实现动态路由的示例
2017/09/15 Javascript
解决layui中的form表单与button的点击事件冲突问题
2018/08/15 Javascript
element-ui 设置菜单栏展开的方法
2018/08/22 Javascript
webpack4.x下babel的安装、配置及使用详解
2019/03/07 Javascript
详解如何更好的使用module vuex
2019/03/27 Javascript
vue给对象动态添加属性和值的实例
2019/09/09 Javascript
返回上一个url并刷新界面的js代码
2020/09/12 Javascript
[00:36]我的中国心——Serenity vs Fnatic
2018/08/21 DOTA
Python的SimpleHTTPServer模块用处及使用方法简介
2018/01/22 Python
python通过elixir包操作mysql数据库实例代码
2018/01/31 Python
python自带tkinter库实现棋盘覆盖图形界面
2019/07/17 Python
tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this T
2020/06/22 Python
使用pygame实现垃圾分类小游戏功能(已获校级二等奖)
2020/07/23 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
2020/10/15 Python
工程现场管理求职自荐信
2013/10/02 职场文书
缓刑人员的思想汇报
2014/01/11 职场文书
数控专业个人求职信范文
2014/02/05 职场文书
人力资源作业细则
2014/03/03 职场文书
预备党员的自我评价
2014/03/12 职场文书
音乐兴趣小组活动总结
2014/07/07 职场文书
党员自评材料范文
2014/12/17 职场文书
理想国读书笔记
2015/06/25 职场文书
《钢铁是怎样炼成的》高中读后感
2019/08/07 职场文书
javascript的var与let,const之间的区别详解
2022/02/18 Javascript