底层技术分享:UTF-8/ANSI编码的混用方案终于完成(亦可拟UTF-8编码)

王志勇 发表于 2019年02月01日 13:26

实现这一功能,以前想得太难,其实比较简单。开发中发现,PHP5(及以上的版本)对于UTF-8、ANSI等编码的转换、调用,很完美,所以一个站点完全可以多种编码混用。一个中文字符,在数据库中,UTF-8编码占用3字节,GBK(ANSI)编码占用2字节,因此对于中文页面,ANSI编码可以提高20%~30%的性能,节省相应的流量。

对于个人空间的程序,流量大的网页是博客、微博。所以在将要开发的独立微博Eachval项目,将支持UTF-8、ANSI编码的切换,微博主可以用UTF-8编码,也可以切换到ANSI编码。(为什么在开发初期就一定要支持这个功能?因为这个功能关联的数据库太多,最好一次做好,否则将来改起来工作量不可估量。)

对于流量大的中文官方网站、平台页面、论坛页面,采用UTF-8/ANSI编码混用,是较为理想的方案,比如几年前的百度贴吧就是采用UTF-8/ANSI编码混用,后来又改成UTF-8编码。

UTF-8是相对兼容性好一些的编码,但不是所有的设备(客户端)都能完全兼容。比如,我在英文版CentOS系统下安装桌面、火狐浏览器,浏览UTF-8的网页,所有中文网页的全角字符,全部显示为方格或者乱码,此时还是需要安装中文包,如下图。为什么会出现这种问题呢?可能是因为国外的开发者,开发时没有完全做多语言测试,所以会有此bug。

本文分享的UTF-8/ANSI编码混用、或者拟UTF-8编码,方法是决定一个网页的语言,header()语句的优先级高于HTML代码的<meta>标签,例如,如果一个网页同时写入这2个语句:
<?header('Content-Type:text/html;charset=utf-8');?>
<meta http-equiv="Content-Type" content="text/html;charset=gbk">
第2行的HTML5代码是<meta charset="gbk" />

测试中,浏览器的语言会被设定为UTF-8。这时,<meta>标签的语言设定是无效的。本文标题的括号里的“拟UTF-8编码”,就是说网页实际是GBK编码,但是HTML代码里又声明是UTF-8编码,如果不加以分析,是完全看不出来其实是一个GBK的网页。实际运用中,中文网页用GBK性能更高;但是UTF-8编码是中文网页的潮流。

以前大部分中文网页都是GB2312或GBK编码,现在几乎都换成了UTF-8编码。为了解决这一问题,保持高性能,又不失潮流,就可以采用这种拟UTF-8编码的方法,<meta>标签的语句想怎么写都可以。方法如下,也就是把上述语句的语言对调:
<?header('Content-Type:text/html;charset=gbk');?>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
第2行的HTML5代码是<meta charset="utf-8" />

保存php文件时,在EmEditor下,GBK应该保存为ANSI字符码;UTF-8应该保存为UTF-8字符码,否则会出现乱码。

测试中,数据库的写入,编码并不以header()语句为优先级。有2个因素都会优先决定数据库的编码格式,一是php文件自身的文件编码格式;二是<meta>标签的charset语言设置。所以,为了解决这个问题,可以把charset这7个字符,改成任意的字符,使这个<meta>标签失效,这样就完美地解决不同编码间post时产生的乱码。

除了上述的2个因素,决定写入数据库的编码格式,还有第3个因素,iconv()语句可以改变将要写入的编码格式。测试中,iconv语句转换后的(编码)格式,就是存储的格式。比如一个网页是基于UTF-8编码,想写入ANSI编码,可以这样先转换:
$a1=iconv('UTF-8','GBK//IGNORE',$a1);
$a1这个值写入的数据库,就是GBK(ANSI)编码格式。或者GBK编码下,想入UTF-8编码,则用这个相反的语句:
$a1=iconv('GBK','UTF-8//IGNORE',$a1);

UTF-8网页打开并调用GBK的数据库,或者GBK网页打开UTF-8的数据库,同样用上述的这2个iconv语句转换,完美解决所有的乱码。

0条评论:

发表评论:
名字: (*必填)
博客: (可省)

正文:

  记住信息?

王志勇:1980-09-26 (44周岁)
程序设计,前端设计。

版权声明:本博客所有文章,均符合原创的定义,禁止转载,违者将必究;正确的方法是贴原文的标题和网址即可。

与此相关的链接
自由勇专栏

Blog存档 Archives

2022年07月
2022年06月(15)
2022年05月(20)
2022年04月(16)
2022年03月(9)
2022年02月(9)
2022年01月(10)
2021年 +

2020年 +
2019年 +
2018年 +
2016年-2017年(9)
2014年06月-09月(10)
2013年 +
2012年 +
2011年 +
2010年 +
2009年 +
2008年 +
2007年 +
2006年 +
2005年09月(4)

Copyright © 2006-2024 auiou.com All rights reserved.
此Blog程序由王志勇编写