首页 > 程序开发 > 关于BOM头

关于BOM头

2008年9月26日

要命的BOM头让我吃了两次亏,每次都是莫名奇妙地花了1,2天才找出问题。
第一次是:写ZF的errorControler设置404返回值的时候报错:
Cannot modify header information - headers already sent
检查了那个有名的ZF最后一个结束符不写的问题和setRawHeader的代码,都找不出症结所在,后来发现是BOM头捣鬼。
今天又碰到这个问题,导入系统一个excel文件,老有错,仔细检查是第一行含有bom头,所以数据老是读错,害我花了半天的时间找问题。

在Windows下用记事本之类的程序将文本文件保存为UTF-8格式时,记事本会在文件头前面加上几个不可见的字符(EF BB BF),就是所谓的BOM(Byte order Mark)。

php4/5会视BOM为一般字符输出(这是一个不可见字符),因此会出现这个header already sent的问题。应该说这是一个php的bug(22108, 42312),可喜的是,php6宣传已经没有这个问题,而在php4/5下,有两个方法可以解决这一问题:
方法一,可以在保存文件的时候设置不使用BOM头格式的UTF8文件。
dreamweaver设置如下:

UltraEdit可以设置(Configuration-> File Handling -> Save -> Write UTF-8 BOM header),
也可以直接修改C:\Windows\UEdit32.ini,增加以下两行设置
Write UTF-8 BOM=0
Write UTF-8 BOM NF=0

此外HTML代码中的codepage及charset也必须要设定,以保证编码方式正确。

方法二,以上方式可以解决自己写的代码,却不能解决用户上传的文件。这种情况下,需要在服务器端判断文件头,并截取相应的三个字符(0xEF 0xBB 0xBF),以下代码是FCKeditor的一段代码,由于考虑到可能要处理的文件较大,所以将传值函数改成传递引用:
//strip UTF8 BOM if any
function StripUtf8Bom( &$data ){
  if ( substr( $data, 0, 3 ) == "\xEF\xBB\xBF" ){
   $data=substr_replace( $data, '', 0, 3 ) ;
   return TRUE;
  }
  return FALSE;
}

关于为何能提高性能,见风雪之隅的博客介绍的php传递引用的实现

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

程序开发

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.

This blog is kept spam free by WP-SpamFree.