PHP正确解析UTF-8字符串

  1. $str = '今天非常Happy,所有决定去KFC吃可乐鸡翅!!!';
  2. /*
  3. $str 是待截取的字符串
  4. $len 是截取的字符数
  5. */
  6. function utf8sub($str,$len) {
  7. if($len <= 0){
  8. return '';
  9. }
  10. $offset = 0; // 截取高位字节时的偏移量
  11. $chars = 0; // 截取到的字符数
  12. $res = ''; // 存放截取的结果字符串
  13. while($chars < $len){
  14. // 先取字符串的第一个字节
  15. // 将它转为十进制
  16. // 再转为二进制
  17. $high = ord(substr($str,$offset,1));
  18. // echo '$high='. $high .'<br />';
  19. if($high == null ){ // 如果取出高位为null,证明已经取到末尾,直接break
  20. break;
  21. }
  22. if(($high>>2) === 0x3F){ // 将高位右移2位,和二进制111111比较,相同则取6个字节
  23. // 截取2个字节
  24. $count = 6;
  25. }else if(($high>>3) === 0x1F){ // 将高位右移2位,和二进制11111比较,相同则取5个字节
  26. // 截取3个字节
  27. $count = 5;
  28. }else if(($high>>4) === 0xF){ // 将高位右移2位,和二进制1111比较,相同则取4个字节
  29. // 截取4个字节
  30. $count = 4;
  31. }else if(($high>>5) === 0x7){ // 将高位右移2位,和二进制111比较,相同则取3个字节
  32. // 截取5个字节
  33. $count = 3;
  34. }else if(($high>>6) === 0x3){ // 将高位右移2位,和二进制11比较,相同则取2个字节
  35. // 截取6个字节
  36. $count = 2;
  37. }else if(($high>>7) === 0x0){ // 将高位右移2位,和二进制0比较,相同则取1个字节
  38. $count = 1;
  39. }
  40. // echo '$count='.$count.'<br />';
  41. $res .= substr($str,$offset,$count); // 取出一个字符与$res字符串连接
  42. $chars += 1; // 截取到的字符数+1
  43. $offset += $count; // 截取高位偏移量向后移$count字节
  44. }
  45. return $res;
  46. }
  47. echo utf8sub($str,100);