PHP接收GET中文参数乱码深入研究 [PHP]
post by 朦朧中的罪惡 / 2010-6-18 10:29 Friday
相信很多PHPer都会遇到这样的问题:在utf-8的页面下面,如果直接访问带有中文参数的地址如test.php?s=测试 这样的地址输出参数的值会乱码,在搜索引擎上查询了下相关资料,都只给出了一些解决方案,但是却没有人研究导致这个问题的原因,今天特写此文来深入这个问题产生的原因:
首先我们演示这个问题,测试代码和运行结果如下。
代码:
测试结果:
代码中声明了响应内容的编码为utf-8,显示的内容确实乱码。
在这里请注意var_dump出变量的长度只有4 ,很显然,两个中文字的长度在utf-8编码下肯定不止4个字节
然后我们再看一下Firefox的访问这个页面url
FireFox会自动将中文url编码,所以我们可以看到测试变成了%B2%E2%CA%D4,很明显,这里一个字是两个字节,是gb2313、gbk等中文编码格式,而不是utf-8编码。
如果我们把页面的编码切换为gbk,中文参数就会显示正常,参见下图
这时一个有趣的问题就诞生了:像emlog的中文标签这样的参数怎么就没有乱码呢?
多方测试后,我发现了一个小小的区别:
emlog中文参数的链接是在页面上生成的,而上面我们测试则用手直接在地址栏输入的,
如果我们直接输入例如http://be-evil.org/?tag=原创 这样的链接,程序同样会提示找不到标签
测试代码如下:
测试结果,正常显示:
请注意上图中红框标出的url编码,这次测试两个字是由6个字节组成,而不是先前的2个字节,因此表明中文参数已经正确的成为utf-8编码。
那么,是什么导致这个问题的发生呢?
答案是浏览器默认编码 在作怪,我们都用的是中文系统,浏览器默认的编码自然也会设置为本地化,例如我自己电脑上的IE的FireFox的默认编码都是gb系列的,请参看下图:
IE的默认设置:
Firefox的默认设置:
正因为这个设置,让浏览器在请求用户输入的url 时会默认把url中的中文以默认的编码格式发送而不是以页面的编码格式发送,这就是为什么页面中带有中文的链接正常而我们手动输入的链接会乱码的原因。同理,如果我们把浏览器的默认编码调整为utf-8,那么输入url中的中文则会按照utf-8编码。
除了上面的之外,还有以下情况会出现这种情况:
如果gbk编码的页面生成的地址链接到utf-8的页面,gbk页面的中文是按照gbk的格式编码传送给下个页面,那么utf-8编码接收后肯定会出现乱码。
IIS的url重写模块,重写后的中文编码也是gbk,如果你的页面是utf-8编码,那么重写参数将会失效。
像这些情况,我们就需要使用php内置的转码函数来处理编码问题了:
方案1:
$str = iconv("gb2312","utf-8",$str);
方案2:
mb_convert_encoding($str, "utf-8", "gb2312");
希望本文对那些因为编码问题而抓破头的PHPer们有所帮助 :)
PHP匹配GBK全中文字正则表达式(不包括GBK标点符号) [PHP]
post by 朦朧中的罪惡 / 2010-6-12 10:03 Saturday
今天朋友让我帮他弄个正则表达式,要求如下:
编码为gbk,要求,a-z,0-9,只匹配中文字不包括中文的标点符号如# ¥ % &等
查了下资料,网上匹配GBK中文的表达式都是使用16进制码通杀中文的那种
例如 "/^[".chr(0xa1)."-".chr(0xff)."]+$/" ,依然会把C 这样的的字符匹配进去
测试代码如下:
测试结果:
去维基百科查阅相关资料 ,GBK的编码范围如下:
根据资料继续查阅GBK码表 ,
前面提供的表达式是从A1就开始了,而A1-A9正好就是符号段,难怪会匹配到
排除符号段后就可以得出中文字符的码段为0xB0 - 0xF7,0x81 - 0xA0, 0xAA - 0xFE
按照编码标准,中文字由两个字节组成,那么我们按照标准建立正则表达式
(([\xB0-\xF7][\xA1-\xFE])|([\x81-\xA0][\x40-\xFE])|([\xAA-\xFE][\x40-\xA0])|(\w))+
测试代码如下:
运行结果,成功匹配中文字符,问题解决
Android查看sqlite数据库内容的方法 [Android]
post by 朦朧中的罪惡 / 2010-6-10 20:24 Thursday
Android中可以采用sqlite数据裤来存储数据,是Google却没有直接给我们提供相关工具来管理数据库里的数据。
如果不能直接通过工具来查看,那我们就把数据库从手机/模拟器里面拷贝出来用工具查看,下面是步骤
1.确认数据库的位置
我们可以通过eclipse的DDMS插件来访问手机的部分目录
数据库文件位于/data/data/你的程序的包名/databases/中,下图是一个例子
2.拷贝出数据库文件
我们可以用adb工具来下载数据库文件
命令为 adb push 手机路径 本地路径
例如我要把项目下的test.db数据拷贝到我的桌面,那么运行命令
./adb pull /data/com.test/databases/test.db ~/Desktop/
3.打开数据库文件
这里不用多说,去sqlite官方 选一款软件来读取和管理数据即可
4.更新数据库文件
同样使用adb工具上传
命令为 adb push 本地路径 手机路径
./adb push ~/Desktop/alaTest.db /data/data/com.test/databases/test.db
PHP解析XML异常问题解决 [PHP]
post by 朦朧中的罪惡 / 2010-6-10 10:38 Thursday
今天在调试emlog工具箱导入rss文件时php报错
内容为
Char 0x0 out of allowed range in Entity
Google搜索相关资料无果。郁闷了半天,后来突然想到Char 0x0,觉得这个应该是rss文本中含有非法的字符而导致xml解析失败.
查询了w3.org的xml字符范围 之后
上面定义了有效的uncode字符范围:
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
虽然0x0可以存在于utf-8文件中,但是0x0很明显不在上面规定范围之内
那么我只需要把文档里面不符合上面标准的字符过滤掉应该就能解决这个问题
php函数如下
在解析xml之前使用该函数来过滤掉非法字符,就能解决xml解析异常的问题了
参考资料
Invalid XML Characters: when valid UTF8 does not mean valid XML
PHP识别url重写请求 [PHP]
post by 朦朧中的罪惡 / 2010-6-9 10:28 Wednesday
现在很多PHP程序都使用了url重写技术来优化url,但是有时候我们要在PHP程序中区分默认url的请求和url重写后的请求,这该如何处理呢?
我的解决方案是在常量$_SERVER里面找答案,在不同的服务器中$_SERVER都会有一个索引用来记录重写请求访问重写之前的路径
根据我的测试,部分主流服务器的索引如下
IIS7 + Rewrite Module -> $_SERVER['HTTP_X_ORIGINAL_URL']
IIS6 + ISAPI Rewite -> $_SERVER['HTTP_X_REWRITE_URL’]
Apache2 -> $_SERVER['REQUEST_URI’] 或 $_SERVER['REDIRECT_URL']
nginx -> $_SERVER['REQUEST_URI’]
有了这个参数,我们就可以在PHP中来判断请求url来自于重写地址的还是默认格式的地址了
ubuntu美化为Mac OS X Leopard桌面 [Linux]
post by 朦朧中的罪惡 / 2010-5-22 23:09 Saturday
一直想把自己的ubuntu折腾的漂亮点(虽然默认主题已经很漂亮了),今天折腾了半天,终于把ubuntu折腾成了Mac OS X Leopard的样式。
效果图
需要软件
Mac4Lin
下载地址:
http://sourceforge.net/projects/mac4lin/
avant-window-navigator
安装步骤:
首先安装MacLin
下载压缩包之后解压缩,进入文件夹
直接运行Mac4Lin_Install_v1.0.sh即可完成安装
然后再安装avant-window-navigator
在命令行中输入 sudo apt-get install avant-window-navigator
安装完毕后然后再输入avant-window-navigator即可启动高仿的Dock了
如果想让avant-window-navigator保持开机启动,则需要在系统的启动中增加avant-window-navigator
方法为在命令行中运行gnome-session-properties,新增加一个程序全部填写gnome-session-properties即可搞定,参数配置可参考以下设置
mysql_fetch_object函数读取SELECT COUNT(*)数据的方法 [PHP]
post by 朦朧中的罪惡 / 2010-5-18 21:57 Tuesday
mysql_fetch_object 函数返回的对象形式的数据
但是遇到在SQL语句中出现SELECT Count(*)和 SELECT SUM等情况时,就不能使用上面的方法取得列的数据了,目前的解决方案是给Count(*)增加一个别名,请看下面的代码:
起了别名之后,我们就可使用与别名同名的属性来访问列的数据了。
最后,这个解决方案除了mysql_fetch_object之外,还适用于mysql_fetch_assoc函数
ubuntu配置TortoiseHg的对比工具meld [Linux]
post by 朦朧中的罪惡 / 2010-5-4 20:22 Tuesday
首先需要安装相关的工具,版本控制软件mercurial,对比工具meld,mercurial图形工具tortoisehg
sudo apt-get install mercurial meld tortoiseh
安装好这些后编辑你的~/.hgrc文件,增加以下内容:
[ui]
merge = meld
[tortoisehg]
vdiff = meld
[extensions]
hgext.extdiff =
[extdiff]
cmd.meld =
配置完成之后,只要启动tortoisehg就可以使用meld来对比了,过程参见下图
选择要对比的文件后右键,再选择 Visual Diff
双击选中文件
然后就可以开始对比了
手动删除Firefox中一些无法卸载的扩展 [Firefox]
post by 朦朧中的罪惡 / 2010-4-21 12:43 Wednesday
安装skype的时候没注意选择,结果skype给我的Firefox安装了一个扩展,让我吐血的是想卸载这个扩展的时候却发现卸载的按钮是灰色的。
同样流氓的扩展还有安装JDK以后出现的两个Java Console
没办法,看来得手工删除了。
首先跑去Firefox存储用户的文件夹搜索这几个扩展,无果
在Windows7下面的路径为:
C:\Users\{用户名}\AppData\Roaming\Mozilla\Firefox\Profiles\{随机码}.default\extensions
在XP的路径为:
C:\Documents and Settings\{用户名}\Application Data\Mozilla\Firefox\Profiles\{随机码}\extensions
附,鉴定扩展的方法:
有的扩展文件夹的名称是基于邮箱的,所以比较好找如firebug的是firebug@software.joehewitt.com
但是有的扩展是用的GUID来命名例如FireFtp的文件夹叫做{a7c6cf7f-112c-4500-a7ea-39801a327e5f}
这时我们可以用任意文本编辑器打开每个扩展文件夹下面的install.rdf,然后查看xml字段<em:name></em:name>中的名称即可确定是哪个扩展
如果个人文件夹里面没有那么该扩展应该就是公共的,于是去firefox的安装路径下面寻找扩展文件夹
skype的插件果然在里面
删除几个相关的文件夹,重启firefox后那几个插件就消失了,问题解决
PHP计算相关两个时区的时间差 [PHP]
post by 朦朧中的罪惡 / 2010-4-19 9:03 Monday
我们在开发通用PHP程序的时候可能遇到这样的情况:
服务器配置的时区和用户的时区不一样,而不同的用户也可能子在不同时区,不同的服务器默认的时区也不会不一样,那么就会经常涉及一个不同时区时间转换的问题,而获得不同时区的时差就是一个很头疼的问题。
PHP在5.1之后提供了一个DateTimeZone来帮助我们转换时区的时间,我们可以使用这个类来处理时间转换的问题
下面看代码(点击放大):
参考资料 http://cn.php.net/manual/en/function.timezone-offset-get.php
详细代码可以参见附件 timezone.php
附件下载:
timezone.zip 659字节




























