当前位置:Gxlcms > PHP教程 > php中文字符串截断且无乱码的解决方法

php中文字符串截断且无乱码的解决方法

时间:2021-07-01 10:21:17 帮助过:12人阅读

  1. function substring($str, $start, $length){ //比较好用字符串截取函数
  2. $len = $length;
  3. if($length < 0){
  4. $str = strrev($str);
  5. $len = -$length;
  6. }
  7. $len= ($len < strlen($str)) ? $len : strlen($str);
  8. $tmpstr = "";
  9. for ($i= $start; $i < $len; $i ++)
  10. {
  11. if (ord(substr($str, $i, 1)) > 0xa0)
  12. {
  13. $tmpstr .= substr($str, $i, 2);
  14. $i++;
  15. } else {
  16. $tmpstr .= substr($str, $i, 1);
  17. }
  18. }
  19. if($length < 0) $tmpstr = strrev($tmpstr);
  20. return $tmpstr;
  21. }
  22. ?>

使用方法示例:

  1. $str1 = '我是一串比较长的中文不带英文';

  2. $str2 = '我是一串比较长的中文带yingwen';

  3. $len = strlen($str1);

  4. echo '
    '.$len; //return 28

  5. $len = strlen($str2);

  6. echo '
    '.$len; //return 29

  7. echo '
    ';

  8. echo substring($str1, 0, 11);
  9. echo '
    ';
  10. echo substring($str2, 0, 11);
  11. echo '
    ';
  12. echo substring($str1, 16, 28);
  13. echo '
    ';
  14. echo substring($str2, 16, 29);
  15. ?>

结果显示: 28 29 我是一串比较 我是一串比较 中文不带英文 中文带yingwen

这个函数十分有用,比如用来截断比较长的文件名,但是要在中间加上...,可以这样来做:

  1. function formatName($str, $size){
  2. $len = strlen($str);
  3. if(strlen($str) > $size) {
  4. $part1 = substring($str, 0, $size / 2);
  5. $part2 = substring($str, $len - ($size/2), $len);
  6. return $part1 . "..." . $part2;
  7. } else {
  8. return $str;
  9. }
  10. }
  11. ?>

另外,网上看到一种超级简单的中文截断解决方案,经测试,效果很不错:

  1. echo substr($str1,0,10).chr(0);
  2. ?>

原理解释: chr(0)不是null null是什么都没有,而chr(0)的值是0。表示成16进制是0x00,表示成二进制是00000000 虽然chr(0)不会显示出什么,但是他是一个字符。 当汉字被截断时,根据编码规则他总是要把后边的其他字符拉过来一起作为汉字解释,这就是出现乱码的原因。而值为0x81到0xff与0x00组合始终都显示为“空” 根据这一特点,在substr的结果后面补上一个chr(0),就可以防止出现乱码了

20120705更新: 以上方法虽好,但是偶尔还是会碰到乱码,原因未深究。不过可以用以下的方法,对UTF8字符文本屡试不爽。 注意:该方法中将汉字计算为1单位长度,英文一个字母1单位长度,所以截断时需要注意长度设置。 计算长度的方法:

  1. function strlen_UTF8($str)

  2. {
  3. $len = strlen($str);
  4. $n = 0;
  5. for($i = 0; $i < $len; $i++) {
  6. $x = substr($str, $i, 1);
  7. $a = base_convert(ord($x), 10, 2);
  8. $a = substr('00000000'.$a, -8);
  9. if (substr($a, 0, 1) == 0) {
  10. }elseif (substr($a, 0, 3) == 110) {
  11. $i += 1;
  12. }elseif (substr($a, 0, 4) == 1110) {
  13. $i += 2;
  14. }
  15. $n++;
  16. }
  17. return $n;
  18. } // End strlen_UTF8;

  19. ///字符串截断函数:

  20. function subString_UTF8($str, $start, $lenth)
  21. {
  22. $len = strlen($str);
  23. $r = array();
  24. $n = 0;
  25. $m = 0;
  26. for($i = 0; $i < $len; $i++) {
  27. $x = substr($str, $i, 1);
  28. $a = base_convert(ord($x), 10, 2);
  29. $a = substr('00000000'.$a, -8);
  30. if ($n < $start){
  31. if (substr($a, 0, 1) == 0) {
  32. }elseif (substr($a, 0, 3) == 110) {
  33. $i += 1;
  34. }elseif (substr($a, 0, 4) == 1110) {
  35. $i += 2;
  36. }
  37. $n++;
  38. }else{
  39. if (substr($a, 0, 1) == 0) {
  40. $r[ ] = substr($str, $i, 1);
  41. }elseif (substr($a, 0, 3) == 110) {
  42. $r[ ] = substr($str, $i, 2);
  43. $i += 1;
  44. }elseif (substr($a, 0, 4) == 1110) {
  45. $r[ ] = substr($str, $i, 3);
  46. $i += 2;
  47. }else{
  48. $r[ ] = '';
  49. }
  50. if (++$m >= $lenth){
  51. break;
  52. }
  53. }
  54. }
  55. return join($r);
  56. } // End subString_UTF8;

  57. //使用方法和之前介绍的一样,比如formatName可以实现如下(这对汉字长度做了小优化):

  58. function formatName($str, $size){
  59. $len = strlen_UTF8($str);
  60. $one_len = strlen($str);
  61. $size = $size * 1.5 * $len / ($one_len);
  62. if(strlen_UTF8($str) > $size) {
  63. $part1 = subString_UTF8($str, 0, $size / 2);
  64. $part2 = subString_UTF8($str, $len - ($size/2), $len);
  65. return $part1 . "..." . $part2;
  66. } else {
  67. return $str;
  68. }
  69. }
  70. ?>

人气教程排行