- 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 '
'.$len; //return 28 $len = strlen($str2); - echo '
'.$len; //return 29 echo ' '; - echo substring($str1, 0, 11);
- echo '
'; - echo substring($str2, 0, 11);
- echo '
'; - echo substring($str1, 16, 28);
- echo '
'; - 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
null是什么都没有,而chr(0)的值是0。表示成16进制是0x00,表示成二进制是00000000
虽然chr(0)不会显示出什么,但是他是一个字符。
当汉字被截断时,根据编码规则他总是要把后边的其他字符拉过来一起作为汉字解释,这就是出现乱码的原因。而值为0x81到0xff与0x00组合始终都显示为“空”
根据这一特点,在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;
- }
- }
- ?>
|