免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6051 | 回复: 10
打印 上一主题 下一主题

如何利用PHP来截取一段中文字符串而不出现乱码 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-11-25 14:34 |只看该作者 |倒序浏览
标题:如何利用PHP来截取一段中文字符串而不出现乱码

作者:jeffwu(jeffwu_cn@hotmail.com)

  1. /*
  2. 功能:截取全角和半角混合的字符串以避免乱码
  3. 参数:
  4.         $str_cut        需要截断的字符串
  5.         $length  允许字符串显示的最大长度

  6. */

  7. function substr_cut($str_cut,$length = 30){

  8.         if (strlen($str_cut) >; $length){
  9.   for($i=0; $i < $length; $i++)
  10.           if (ord($str_cut[$i]) >; 128)        $i++;
  11.   $str_cut = substr($str_cut,0,$i) . "...";
  12.         }
  13.         return $str_cut;
  14. }

复制代码

说明:
        程序的关键语句是:

  1.         for($i=0; $i < $length; $i++)
  2.                 if (ord($str_cut[$i]) >; 128)        $i++;
  3.        
  4.         $str_cut = substr($str_cut,0,$i) . "...";
复制代码

        如果字符的ASCII码大于128,说明当前字符和下一个字符是属于一个汉字的。
        则,$i++ 跳过对下一个字符的判断。
        再结合循环中的 $i++ ,实际上,当遇到一个汉字时,$i 就会加 2 ,从而正确的跳过汉字。
        最终实现的效果是,$i 变量指向的要么是半角的字符,要么是全角汉字的首字符,不会指向
        全角汉字的第二个字符,所以,当$i >;= $length 时,循环结束,使用
        $str_cut = substr($str_cut,0,$i) . "..."; 截取字符时自然也就不会出现乱码了。


本人在写一个程序时需要利用PHP从一段字符串中截取指定长度的一段字符下来。以前在写ASP的时候,参考动网的程序写过类似的程序,不过,还没用PHP写过。

想偷懒,看有不有现成的代码可以用。于是,在GOOGLE中输入:PHP 截断字符 后查找到一段代码。

全文:http://www.yesky.com/SoftChannel ... 510/1610570_3.shtml

引用:
#########################################################################
  如何分别全角和半角以避免乱码?

  我们可以写这样一个函数来实现:

  1. function ChgTitle($title)
  2. {
  3. $length = 46; //我们允许字符串显示的最大长度
  4. if (strlen($title)>$length) {
  5. $temp = 0;
  6. for($i=0; $i<$length; $i++)
  7. if (ord($title[$i]) > 128) $temp++;
  8. if ($temp%2 == 0)
  9. $title = substr($title,0,$length)."...";
  10. else
  11. $title = substr($title,0,$length+1)."...";
  12. }
  13. return $title;
  14. }  
复制代码

  这个函数原理就是截断一个字符,看看其ascII码是不是大于128,如果是,说明截断的是一个全角汉字,那么就退后一个截断。用$length控制长度

  备注:循环判断字符串里面的 >128 的字符个数,如果半角字符为偶数,则表示位置刚好为整个汉字,如果为奇数,则为半个汉字,需要取下一个字符

#######################################################################

消化、测试这段代码后发现有问题。经过反复调试,查找出,这段代码基于的原理不正确。
它认为,汉字的两个字节其ASCII码都会大于128,其实不然,一个汉字的首个字节的ASCII码
必定是大于128的,但是第二个字节的ASCII码不一定大于128,例如:"祐",其两个字节的ASCII
码分别为:181 和 118。

经过仔细分析,最终,我利用上面的函数实现了对全角和半角字符串的截取。

一点点体会,写出来也是想和大家一起交流、学习。我不知道是不是有人已经写过上面的函数,不过,
我还没能读到,也就只能自己琢磨了,呵呵。

欢迎有兴趣的朋友来信交流。

[ 本帖最后由 jeffwu 于 2008-2-18 17:57 编辑 ]
longnetpro 该用户已被删除
2 [报告]
发表于 2003-11-26 02:26 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
3 [报告]
发表于 2003-11-26 09:01 |只看该作者

如何利用PHP来截取一段中文字符串而不出现乱码

哈哈..楼主例只,只能用于GB2312,如果是GB18030,GBK不知可以吗????

原帖由 "longnetpro"]E\x80-\xFE 发表:
){30}/

我用的方法一贯是:将多字节码(如中文)转换为UNICODE,长度自然就出来了。不过一般只针对长度比较短的字符串,因为在一般的PHP编程中很少需要分析长的多字节编码的字符串(如求长度或是截取?.........


我的整个站点都是UTF-8的..数据库使用UNICODE 数据存储UTF-8

member=>; select substring('数据库的编码是用系统表' from 1 for 4);

substring

-----------

数据库的

(1 row)



member=>; select substring('数据库的编码是用系统表' from 1 for 2);

substring

-----------

数据

(1 row)



member=>; select * from 组;

序号 |     组名     |         描述

------+--------------+----------------------

    1 | 域用户       | 9812.net域内用户

    3 | 计算机维护组 | 维护计算机的用户用户

(2 rows)



member=>; select 组名,substring(描述 from 1 for 5) as 描述 from 组;

     组名     |    描述

--------------+------------

域用户       | 9812.

计算机维护组 | 维护计算机

(2 rows)
longnetpro 该用户已被删除
4 [报告]
发表于 2003-11-26 11:20 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
5 [报告]
发表于 2003-11-26 17:06 |只看该作者

如何利用PHP来截取一段中文字符串而不出现乱码

原帖由 "longnetpro" 发表:
你这个是对特殊设置的数据库可行,比较通用的办法还是用PHP即时转换吧。

我前一个月写了一个汉字编码转换的程序,支持UTF8,UTF16BE、LE,UTF32BE、LE,GB18030,BIG5的互转,支持繁简互转,中间代码用UNICODE。
..........


不支持UNICODE.的数据就是不合格产品..

你那么转来转去.烦不烦...影响性能...
如果要转码.使用iconv 函数就行了.编译时加--with-iconv
数据本身也支持
select convert(描述,'UNICODE','GBK')as desc from 组;
select convert(组名 using utf_8_to_gb18030) from 组;

http://home.9812.net/linux/article/postgres/postgresql.htm

请看看..
11.8.2 PHP
longnetpro 该用户已被删除
6 [报告]
发表于 2003-11-26 20:35 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
7 [报告]
发表于 2003-11-27 09:08 |只看该作者

如何利用PHP来截取一段中文字符串而不出现乱码

原帖由 "longnetpro" 发表:


不支持UNICODE的数据就是不合格产品?可能你这么认为,可很多老外并不这么认为的。其实说白了,UNICODE还是为了照顾非拉丁文字语言而搞的,它为什么一定要支持?因为UNICODE只是一个组织定的标准,并不一定被所有..........


这是直接使用UNICODE与间接使用... 的问题.

UNICODE还是为了照顾非拉丁文字语言而搞的..不是为了"照顾".
而是为了跨平台兼容..

UNICODE 使你的数据库可以存储,中文(繁,简,蒙古,藏文....),日文,韩文.啊拉伯..等等.....
一个中文汉字长=假名长=韩文长=啊拉伯字长=英文.......
好处不用说...

所以以后发表结论的时候请客观一点,看问题的视角多一点,不是只从自己出发。


你可以看看我写的文档..
http://home.9812.net/linux/article/postgres/postgresql.htm

11.8       汉字编码问题


文中提供了.4转码方案.(包括原代码) 视角还不够多吗? 目前还没想出其它方案.
longnetpro 该用户已被删除
8 [报告]
发表于 2003-11-27 10:04 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
9 [报告]
发表于 2003-11-27 10:26 |只看该作者

如何利用PHP来截取一段中文字符串而不出现乱码

我的方法同样适合SQL99的数据.如Oracle

一般不合格数据都是SQL92的.如果他不支持UNICODE.为什么拿到其它国家销售呢..???哈哈...


MS Sqlserver , Sybase 虽然是SQL92但他加了很多自己东东.跟本不是ASNI 的SQL 2 /SQL92

论坛徽章:
0
10 [报告]
发表于 2003-11-28 10:19 |只看该作者

如何利用PHP来截取一段中文字符串而不出现乱码

hehe,这段代码最早是我在phpease.com发表的,来源于几年前作的汉字显示研究

往事不在,phpease.com也关门, 当年php红火的场面也不在了,但欣慰的是用php 的人越来越多了

上面的边界字符还有问题,最好的是判断

是否大于0xa0,这是汉字的第一个字符开始的编码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP