一個bom頭引起的血案

  1. <?php  
  2.   
  3. session_start();  
  4.   
  5. $_SESSION['test'] = 'test';  
  6.   
  7. $_SESSION['name'] = 'name';  
  8.   
  9. $data = serialize($_SESSION);  
  10.   
  11. ...更多後續代碼  
  12.   
  13. ?>  


 

沒有問題,很簡單的一段設置session的代碼。php

可是運行後卻報錯:html

Cannot send session cache limiter - headers already sent (output started at...) on line ...chrome

報錯信息很明顯,就是在session_start()以前有了輸出,致使後面的header發送失敗。瀏覽器

由於不少狀況下<?php  標籤以前空格也會被當作header發送出去的,因此先檢查這個。session

仔細檢查一下,沒有空格,沒有echo ,沒有print等致使輸出的問題,那麼究竟是什麼問題呢?app

應該有不少人都想到了,bom頭。編輯器

對,這裏就是bom頭搞的鬼。編碼

那麼什麼是bom頭呢?spa

 

 

[plain] view plain copy.net

 

  1. BOM: Byte Order Mark  
  2. 就是一個字節順序標籤,相似一個標記,又叫簽名,   
  3.   
  4. BOM簽名的意思就是告訴編輯器當前文件採用何種編碼,方便編輯器識別,可是BOM雖然在編輯器中不顯示,可是會產生輸出,就像多了一個空行。  
  5. 通常的編碼集中並不會出現bom頭,unicode編碼集中會出現。  
  6. 常見的bom頭是:【摘錄自:http://www.cnblogs.com/chengmo/archive/2010/10/30/1864004.html】  
  7.   
  8.   UTF-8    ║ EF BB BF   
  9.   UTF-16LE ║ FF FE (小尾)  
  10.   UTF-16BE ║ FE FF (大尾)  
  11.   UTF-32LE ║ FF FE 00 00   
  12.   UTF-32BE ║ 00 00 FE FF  
  13.   
  14. 爲何bom頭會產生亂碼?  
  15.   
  16. 【摘錄自:http://www.cnblogs.com/chengmo/archive/2010/10/30/1864004.html】  
  17.   
  18. 有bom頭的存儲或者字節流,它必定是unicode字符集編碼。到底屬於那一種(utf-8仍是utf-16或是utf-32),經過頭能夠判斷出來。  
  19.   
  20. 因爲已經說過utf-16,utf-32不指定bom頭,解析程序默認就認爲是ansi編碼,出現亂碼。而utf-8指定或者不指定程序均可判斷知道對於的字符集編碼。  
  21.   
  22. 問題就出在這裏,可能有的應用程序(ie6瀏覽器),它就認爲若是utf-8編碼,就不須要指定bom頭,它能夠本身判斷,相反指定了bom頭,它還會出現問題  
  23.   
  24. (由於它把頭當utf-8解析出現亂碼了)。這裏不截圖了,cnblogs裏面談這個比較多,目前ie6會出現問題。其它ie7+,firefox,chrome不會出現,會忽略掉bom頭。  
  25.   
  26. 統一解決辦法是:存爲utf-8編碼是,不須要加入bom頭,其它utf-16,utf-32加入。  


 

 

知道了這個,解決方案就很明顯了:把utf-8的bom頭去掉便可。

方式就是文件編碼格式選擇utf-8無bom。


另摘錄一個網上找來的去除bom頭的代碼:

 

[php] view plain copy

  1. <?php  
  2. if (isset($_GET['dir'])){//config the basedir  
  3.     $basedir=$_GET['dir'];  
  4. }else{  
  5.     $basedir= '.';  
  6. }  
  7.   
  8. $auto = 1;  
  9.   
  10. checkdir($basedir);  
  11.   
  12. function checkdir($basedir){  
  13.     if($dh = opendir($basedir)) {  
  14.         while(($file = readdir($dh)) !== false) {  
  15.             if($file != '.' && $file!= '..'){  
  16.                 if(!is_dir($basedir."/".$file)) {  
  17.                     echo"filename: $basedir/$file".checkBOM("$basedir/$file")."<br>";  
  18.                 }else{  
  19.                     $dirname= $basedir."/".$file;  
  20.                     checkdir($dirname);  
  21.                 }  
  22.             }  
  23.         }  
  24.     closedir($dh);  
  25.     }  
  26. }  
  27.   
  28. function checkBOM ($filename) {  
  29.     global$auto;  
  30.     $contents= file_get_contents($filename);  
  31.     $charset[1] =substr($contents, 0, 1);  
  32.     $charset[2] =substr($contents, 1, 1);  
  33.     $charset[3] =substr($contents, 2, 1);  
  34.     if(ord($charset[1]) == 239 && ord($charset[2]) == 187 &&ord($charset[3]) == 191) {  
  35.         if($auto == 1) {  
  36.             $rest= substr($contents, 3);  
  37.             rewrite ($filename,$rest);  
  38.             return("<font color=red>BOM found,automatically removed.</font>");  
  39.         }else {  
  40.             return("<font color=red>BOM found.</font>");  
  41.         }  
  42.     }  
  43.     elsereturn ("BOM Not Found.");  
  44. }  
  45.   
  46. function rewrite ($filename,$data) {  
  47.     $filenum= fopen($filename,"w");  
  48.     flock($filenum, LOCK_EX);  
  49.     fwrite($filenum,$data);  
  50.     fclose($filenum);  
  51. }  
  52.   
  53. ?>  


 

 

 

另一個常見的bom頭的地方時xml文件。解析失敗的話,有很大一部分緣由是這個。

Error on line 1 of document  : Content is not allowed in prolog. Nested exception: Content is not allowed in prolog.

此時只要去掉bom頭就好了。

特此記錄下來,但願對你們有幫助。

(2011-11-03  happyelements)

相關文章
相關標籤/搜索