检查PHP文件头BOM
前些日子本地文件上传到服务器上,某些文件头部总是出现一条空白,无论怎么修改文件都无法去除空白,用firebug查看header部分同样有一片空白,删除后空白消失,但是在文件里却无法找到那个空白的部分,纠结了好久也没解决;昨天则是后台登陆后显示空白,用的是frameset,单独使用某个部分内容是可以显示的,但是在后台首页index.php下用frameset却无法显示,今天上网查了下,刚好有一个帖子也是说frameset无法显示的问题,有谈到是PHP头文件BOM的影响,之前也了解过PHP头部BOM,知道自己应该是找到问题的答案了(之前的头部空白也是),便查了一下相关BOM的资料.
BOM头
BOM: Byte Order Mark
UTF-8 BOM又叫UTF-8 签名,其实UTF-8 的BOM对UFT-8没有作用,是为了支援UTF-16,UTF-32才加上的BOM,BOM签名的意思就是告诉编辑器当前文件采用何种编码,方便编辑器识别,但是BOM虽然在编辑器中不显示,但是会产生输出,就像多了一个空行,
如果您在修改任何PHP文件後发生:
* 页顶出现一条空白; * frameset无法正常显示(单独使用可以); * 不能登入或者不能登出; * 页顶出现错误警告; * 其它不正常的情况.
这些大部分是编辑器的问题,PHP文件采用UTF-8编码,PHP开发大部分使用的文本编辑软件如:Zend studio、editplus、eclipse等等都可以显示并编辑UTF-8编码的文件,但是也有一些软件不能满足这个要求.
类似如windows的记事本,在保存一个以UTF-8编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM).它是一串隐藏的字符,用于让记事本等编辑器识别这个文件是否以UTF-8编码.对于一般的文件,这样并不会产生什么麻烦.但对于 PHP来说,BOM是个大麻烦.
对于BOM,PHP并不会忽略,在读取、包含或者引用这些文件时,PHP会把BOM作为文件开头正文的一部分,根据嵌入式语言的特点,这串字符将被直接执行(显示)出来.这就导致了一些页面的头部总是有一条白条,尽管样式padding、margin等各方面都设置好也无法让整个网页紧贴浏览器顶部,这头部白条就是这3个不可见的字符(0xEF 0xBB 0xBF,即BOM);
另外还有的问题就是,受COOKIE送出机制的限制,在这些文件开头已经有BOM的文件中,COOKIE无法送出(因为在COOKIE送出前PHP已经送出了文件头),所以登入和登出功能失效.一切依赖COOKIE、SESSION实现的功能全部无效.
所以,在编辑、修改任何文本文件的时候,请使用不会乱加BOM的编辑器.Linux下的编辑器应该都没有这个问题.WINDOWS下,请勿使用记事本等编辑器.推荐使用Editplus,Zend studio、eclipse等编辑器.
其他的对于已经添加了BOM的文件,要取消的话,可以用不会乱加BOM的编辑器另存一次.当然也可以使用以下方法去除该目录下所有文件的头部BOM:
把以下代码复制到一个PHP文件里面,运行该PHP文件,就可以批量清除该文件相同目录下所有文件的头部BOM.
<?php if (isset($_GET[‘dir‘])){ //设置文件目录 $basedir=$_GET[‘dir‘]; }else{ $basedir = ‘.‘; } $auto = 1; checkdir($basedir); function checkdir($basedir){ if ($dh = opendir($basedir)) { while (($file = readdir($dh)) !== false) { if ($file != ‘.‘ && $file != ‘..‘){ if (!is_dir($basedir."/".$file)) { echo "filename: $basedir/$file ".checkBOM("$basedir/$file")." <br>"; }else{ $dirname = $basedir."/".$file; checkdir($dirname); } } } closedir($dh); } } function checkBOM ($filename) { global $auto; $contents = file_get_contents($filename); $charset[1] = substr($contents, 0, 1); $charset[2] = substr($contents, 1, 1); $charset[3] = substr($contents, 2, 1); if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) { if ($auto == 1) { $rest = substr($contents, 3); rewrite ($filename, $rest); return ("<font color=red>BOM found, automatically removed.</font>"); }else { return ("<font color=red>BOM found.</font>"); } }else return ("BOM Not Found."); } function rewrite ($filename, $data) { $filenum = fopen($filename, "w"); flock($filenum, LOCK_EX); fwrite($filenum, $data); fclose($filenum); } ?> 指定目录或文件清除BOM: <?php if(isset($_GET[‘dir‘]) && !empty($_GET[‘dir‘])){ //设置文件目录 $basedir=$_GET[‘dir‘]; }else{ $basedir = ‘.‘; } if(empty($_GET[‘filename‘])){ //设置文件 $auto = 1; checkdir($basedir); }else{ $file = $_GET[‘filename‘]; echo "filename: $basedir/$file ".checkBOM("$basedir/$file")." <br>"; } function checkdir($basedir){ if ($dh = opendir($basedir)) { while (($file = readdir($dh)) !== false) { if ($file != ‘.‘ && $file != ‘..‘){ if (!is_dir($basedir."/".$file)) { echo "filename: $basedir/$file ".checkBOM("$basedir/$file")." <br>"; }else{ $dirname = $basedir."/".$file; checkdir($dirname); } } } closedir($dh); } } function checkBOM ($filename) { global $auto; $contents = file_get_contents($filename); $charset[1] = substr($contents, 0, 1); $charset[2] = substr($contents, 1, 1); $charset[3] = substr($contents, 2, 1); if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) { if ($auto == 1) { $rest = substr($contents, 3); rewrite ($filename, $rest); return ("<font color=red>BOM found, automatically removed.</font>"); }else { return ("<font color=red>BOM found.</font>"); } }else return ("BOM Not Found."); } function rewrite ($filename, $data) { $filenum = fopen($filename, "w"); flock($filenum, LOCK_EX); fwrite($filenum, $data); fclose($filenum); } ?>
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。