估计很多人折腾博客时都有过截断字符串的需求,比如显示文章摘要、评论输出等。
通常用到的是 mb_substr() 或 mb_strimwidth(),但是我发现,网上的很多代码并不严谨,比如很多没有加最后的编码参数,不加此参数则使用内部字符编码。
因为通常我们的文件是 UTF-8 编码的,如果内部字符编码不是 UTF-8,就很可能出问题(内部字符编码可以用 mb_internal_encoding() 设置)。
我在自己服务器(默认的内部字符编码为“ISO-8859-1”)上试了一下,详见下面的代码及结果(注释“//”后的内容为结果,其中“口”代表字符被截断后,无法正常显示的字节片段):
[ 本文假定 $str = 'qifu启福'; ] mb_substr($str,0,4) //qifu mb_substr($str,0,5) //qifu口 mb_substr($str,0,6) //qifu口口 mb_substr($str,0,7) //qifu启 mb_substr($str,0,5,'utf-8') //qifu启 mb_substr($str,0,6,'utf-8') //qifu启福
很明显,不指定 UTF-8 编码时,由于中文字符占三个字节,截取时很容易被拆开,一个中文字符相当于三个英文字符。而指定编码以后,才真的是按字符个数,而不是按字节数截取,mb_strimwidth() 也是一样的。
mb_substr() 截取的是字符个数,而 mb_strimwidth() 截取的是字符宽度,如下:
mb_strimwidth($str, 0, 4, '','utf-8') //qifu mb_strimwidth($str, 0, 5, '','utf-8') //qifu mb_strimwidth($str, 0, 6, '','utf-8') //qifu启
可见 mb_strimwidth() 即不是按字节,也不是按字符截取,而是按照宽度。在 php.net 的说明中指出,多字节字符通常是单字节字符的两倍宽度,也就是说,英文字符占一个宽度,中文占两个,宽度不足以截取一个字符时则不取。
当中英文混合时,这个其实比较适合保证截取后的字符串显示宽度一致。但是,如果网页的字体并不是等宽字体,效果也就体现不出来了,因为“m”和“i”所显示的宽度很可能不一样。
另外,mb_strimwidth() 中如果指定截取后末尾添加字符串,则截取宽度包含该字符串,如下:
mb_strimwidth($str, 0, 3, '.','utf-8') //qi.
如果使用这两个函数时,你仔细数一下输出结果,发现字符个数不太对劲,不妨根据本文所述修改代码试一下。
技术创造美,折腾让这成为可能。
哈哈,是有点儿爱折腾~
站点描述“寥寥数语,皆我心之所慨”,这是在说本站一律原创麽?
哈哈,这句话比独立博客还要早,只是为自己内容少做狡辩的,你这么一说,还赋予了它新的含义呢~
思维敏捷,值得学习!
确实很少添加编码参数,不过好像大部分的内部编码都是utf-8吧?这个还真没有研究
不,默认的编码很可能不是utf-8,我的虚拟主机和VPS都试过了。
这个大概也只有像我这种强迫症患者才会去折腾吧
强迫症都是追求完美的人~
取宽度截取??头一次听说。感觉没啥用。
有排版需求时就有用了,尤其中英文混合的情况。
博主山东哪里人
济宁,你呢?
菏泽
难得遇到山东老乡啊,你好你好~
中文不是占2字节吗?
编码不同,占的字节数也不同。
全然看不懂,得好好学习了
用着什么学什么,不用啥都懂嘛。
如同看天书一般唉。。
我写的太乱了,哈哈。
技术文章,顶一下!
哈哈,分享一下~
中文和英文所占的字符不一样,默认的截取函数就很容易出现问题。
的确,所以我觉得strimwidth更好一些,当然,结合css更好。