解决require_once后顶部输出空白行问题
2009年6月25日 by 影子超
最近两天都在解决一个烦恼的事情,显示好好的文件,只因为在其中加入了一个require_once代码包含了另一个文件,CSS显示出来的效果就走了样,愣是要在顶部多留出一条空白,无论怎么修改CSS都无济于事。这平白无故的留白是怎么来的?
不明白就Google吧,这一查,才知道是UTF-8中特有的BOM标记带来的困扰。对于这个BOM我还真是头一回知道,以前写代码总是用GB2312编码,所以也没出现这样的情况。对于BOM的解释,看看这段说明:
在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。更多了解请参见维基百科。
对于这个UTF-8特有的BOM标记,各种浏览器的处理方式不同,Firefox会忽略,而IE则会产生输出或者忽略一次。而输出的效果则是一个空行或者乱码。这刚好就解释了为什么我之前编辑好的文件(含有一个BOM标记)显示正常,当我使用require_once包含进另一个文件时,就产生了两个BOM标记,而浏览器只忽略第一个,第二个BOM标记则被作为空行被输出了。所以出现了明明正常的CSS样式,顶部却多了一个空白行。
Windows就是使用BOM来标记文本文件的编码方式的,所以如果用记事本编写代码,然后另存为UTF-8格式,文件头就会自动加入这个BOM标记。UTF-8编码的文件中,BOM占三个字节,标记值为EF BB BF。
问题是找到了,还得解决才行。网上有介绍说用editplus等专用编辑软件对文件进行另存为操作来删除BOM标记。如果一两个文件用这种方法处理还行,如果整个站成千上万的文件都这样处理恐怕就没人愿意了。
既然知道BOM的标记值为EF BB BF,那就可以写段代码批处理了,于是乎本人写下了如下清除UTF-8中BOM标记的代码:
<?php
//shadowchao.com
$s=0;//统计成功数
$f=0;//统计失败数
//遍历所有文件
function find_allfile(){
$i="*";
while($file=glob($i)){
foreach($file as $s){
if(!is_dir($s))$allfile[]=$s;
}
$i.="\*";
}
return $allfile;
}
//清除BOM标记
function del_bom(){
global $s,$f;
$file=find_allfile();
foreach($file as $fname){
$fname=dirname(__FILE__)."\\".$fname;
$filecont=@file_get_contents($fname);
$bom=substr($filecont,0,3);
$bom=bin2hex($bom);
if($bom=="efbbbf"){ //判断文件中的前3个字节是否为BOM标记值
$filecont=substr($filecont,3);
$result=@file_put_contents($fname,$filecont,LOCK_EX);
if($result){
echo "[file] $fname --- --- <em style=\"color:green\">清除成功</em><br />";$s++;
}else{
echo "[file] $fname --- --- <em style=\"color:red\">清除失败</em>(文件只读或者被占用)<br />";$f++;
}
}
}
}
del_bom();
if($s==0 && $f==0){
echo "<p>所有文件正常,没有发现BOM标记。</p>";
}else{
echo "<p>统计结果:清除成功($s) | 清除失败($f)</p>";
}
?>
清除效果如下图所示:

经过测试,效果还是相当不错,清除这个BOM标记之后,我的CSS样式总算又恢复正常了。欢迎有需要的朋友测试,如有疑问请指正,谢谢!
作者:影子超
原载:影子超博客
尊重版权,转载请保留作者及原载地址链接。


