PHP中文字符串截断无乱码解决方法
作者:令狐葱 发布时间:2024-05-11 09:44:55
标签:php,字符串,乱码
一个比较好用的字符串截取函数:
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;
}
}


猜你喜欢
- 有很多应用项目, 刚起步的时候用MYSQL数据库基本上能实现各种功能需求,随着应用用户的增多,数据量的增加,MYSQL渐渐地出现不堪重负的情
- 前言……最近在学习yolo1、yolo2和yolo3,写这篇博客主要是为了让自己对yolo2的结
- 本文实例讲述了Python面向对象程序设计之类和对象、实例变量、类变量用法。分享给大家供大家参考,具体如下:类和对象:类的定义:用来描述具有
- 需要把一个从csv文件里读取来的数据集等距抽样分割,这里用到了列表表达式和dataframe.iloc先生成索引列表:index_list
- 利用over(),将统计信息计算出来,然后直接筛选结果集declare @t table(ProductID int,ProductName
- 在用HTML(HyperText Markup Language,超文本链接标示语言)语言编写Web页面时,由于所用的Web浏览器对HTML
- 大家好,我是丁小杰!今天和大家分享Pandas中四种有关数据透视的通用函数,在数据处理中遇到这类需求时,能够很好地应对。pandas.mel
- Mac本地环境搭建在Mac系统,我们可以使用MAMP Pro (官方网站:https://www.mamp.info/en/)软件来搭建本地
- 一. 虚拟环境搭建在开发中安装模块的方法:pip install 模块名称之前我们安装模块都是直接在物理环境下安装,这种安装方法,后面一次安
- 正态分布应用最广泛的连续概率分布,其特征是“钟”形曲线。这种分布的概率密度函数为:其中,μ为均值,σ为标准差。求正态分布曲线下面积有3σ原则
- 代码如下: document.getElementById("btnConnect").value = "连接
- 前言:平时根据需求写代码.人工进行测试往往不会面面俱到,还会因为需求的改变繁琐的进行测试通过完成一个测试函数,可以大大简化测试的步骤,并且在
- 目录简介快速使用格式时区cli总结参考简介不管什么时候,处理时间总是让人头疼的一件事情。因为时间格式太多样化了,再加上时区,夏令时,闰秒这些
- XML被设计用来描述数据,其焦点是数据的内容。HTML被设计用来显示数据,其焦点是数据的外观。  
- 前言提示:这里可以添加本文要记录的大概内容:将一个EXCEL等份拆成多个EXCEL将多个小EXCEL合并成一个大EXCEL并标记来源提示:以
- 传染源: 野生动物,可能为中华菊头蝠病毒: 新型冠状病毒 2019-nCoV传播途径: 经呼吸道飞沫传播,亦可
- 本文主要介绍了MySQL8.0.27安装过程中卡在Initializing Database中并报错的解决,具有一定的参考价值,具体如下:报
- 文通过一个操作实例来说明SQL中主标识列IDENTITY的使用技巧。要求:在 sql server 2005中,建立数据表book,在表bo
- 当变量维数加大时很难想象是怎样按不同维度求和的,高清楚一个,其他的应该就很清楚了,什么都不说了,上例子,例子一看便明白…..a=range(
- 完成了UI,我们就需要对数据进行处理了。在开始“数据”的本地存储之前,我们先来了解一下client-side database storag