标签归档:BOM

好一个BOM,折磨了我3天!

至于什么是BOM,请看这篇文章

1月6日
被要求开发UTF-8的PHP站。
上午: 写了几个页面且测试OK。
下午: 出去Happy没动电脑。
晚上: 惊奇的发现DIV在Firefox下不能居中,
于是很郁闷的睡了一觉…… 😦

1月7日
上午: 以为CSS问题,尝试了各种hack,依然没有解决问题。
下午: 满世界求助,依然无解。
晚上: 自以为见了鬼,
于是很痛苦的睡了一觉…… 😥

1月8日
上午: 决定把问题简单化,
删除了多余的CSS、语句、标签,把.php保存为.html,
最后只剩下一个DIV标签和相应的CSS,竟然还不能居中!
又发现把DIV标签另存为另外的HTML文件,竟然可以居中!
此时看到两个内容一样,显示却不一样的html,好像见到了鬼 👿
快疯了……
下午: 冷静思考,排除CSS问题,继续研究HTML。
晚上: 使用杀手锏,满宇宙求助,经小福猪提醒,原来是BOM惹得祸。
彻底疯了……
我怎么就没想到BOM呢,大概最近劳累过度。不过总算解决了问题。
晚上做梦,梦见自己疯过来疯过去的…… 😆

About BOM

吃一堑,长一智。应该对BOM引起重视。

本文探讨的不是BOM本身,而是怎样解决在UTF-8编码下PHP的BOM问题。

这里指的BOM是Byte Order Mark,不是Bill Of Material,也不是Brower Object Model。
那么BOM具体是什么?官方的解释是这样的:
A byte order mark (BOM) consists of the character code U+FEFF at the beginning of a data stream, where it can be used as a signature defining the byte order and encoding form, primarily of unmarked plaintext files. Under some higher level protocols, use of a BOM may be mandatory (or prohibited) in the Unicode data stream defined in that protocol.

另外,fmdd也给出了解释:
在UCS编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符”ZERO WIDTH NO-BREAK SPACE”。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。

简单的说,用Windoes自带的记事本把一个文本文件另存为UTF-8编码,然后用UltraEdit以十六进制打开,就可以看到文件开头的”EF BB BF”,这个就是BOM。程序可以通过BOM来识别文件是否UTF-8编码。对大多数程序来说,这是个很聪明的方法。但遗憾的是,有些程序并不能很好的识别它,例如Win的记事本、Firefox还有PHP。

就UTF-8编码的PHP来说,由于代码必须在<?php code ?>这样的PHP标签中才会执行,而BOM总是在文件头的3个字符中,所以这3个字符会直接输出,在浏览器看到的是乱码或者空行。更严重的是”受COOKIE送出机制的限制,在这些文件开头已经有BOM的文件中,COOKIE无法送出,因为在COOKIE送出前PHP已经送出了文件头。”至于解决方法,很简单,如果只包含英文字符,可以把文件转成ASCII编码,如果包含中文字符,则需要转成没有BOM的UTF-8编码。以UltraEdit_v13为例,打开文件,点击菜单”File”,然后是”Save as”或者直接按快捷键F12,在弹出的对话框中选择”UTF-8-无BOM”即可。不过,您不必那么麻烦,我找到了一款开源免费的轻量级代码编辑器notepad++(点击打开)