最近,在用file_get_contents函數來取得文本的內容的時候,出現了一個情況(如下),苦思冥想了n久,不得其解,最后,果然還是得靠百度啊.....
百度到一個解釋,下面是原文:
PHP5中的file_get_contents函數獲取文件內容,實際是按二進制來讀取的,所以,當你用file_get_contents去獲取一個帶BOM的UTF-8文件時,它並不會把UTF-8的BOM去掉,當你把讀取的內容當作文本內容來進行一些操作時,可能會發生一些意想不到的結果。這並不能算作一個BUG,因為file_get_contents函數讀取文件的時候,是按二進制來讀取的,讀取到的內容是包含BOM的,而用戶操作的時候,想當然的以為讀取到的內容是不包含BOM的文本內容(如用記事本打開后看到的內容),因為BOM在編輯軟件中是不可見的,只有在十六進制模式下才可以看見,問題也就出在這,實際上是由於“操作不統一”造成的。
當對UTF-8編碼的文件進行操作時,如果要把讀取的內容當作文本內容來處理,最好先對BOM進行一些處理,這個問題在PHP6中得到了解決(可以設置文本/二進制讀取模式),有興趣的朋友
可以自己查找PHP6的手冊。
一個較簡單的解決方法:
1 <?php 2 $dataStr = file_get_contents('test.txt'); 3 if (strpos($dataStr, "\xEF\xBB\xBF") === 0) { //\x表示16進制 4 $dataStr = substr($dataStr, 3); 5 } 6 // 對$dataStr進行操作 7 ?>
或者用正則來處理:
1 <?php 2 $dataStr = file_get_contents('test.txt'); 3 if (preg_match('/^\xEF\xBB\xBF/', $dataStr)) {//\x表示16進制 4 $dataStr = substr($dataStr, 3); 5 } 6 // 對$dataStr進行操作 7 ?>
什么是BOM?
BOM是Byte Order Mark的縮寫,即字節順序標記,它是插入到UTF-8,UTF-16或UTF-32編碼的Unicode文件開頭的特殊標記,用來標識Unicode文件的編碼類型。
幾種編碼對應的BOM:
EF BB BF UTF-8
FE FF UTF-16 (big-endian)
FF FE UTF-16 (little-endian)
00 00 FE FF UTF-32 (big-endian)
FF FE 00 00 UTF-32 (little-endian)
對於UTF-8編碼的文件而言,BOM標記是可有可無的,Windows自帶的記事本文件在保存為UTF-8編碼時,會自動加上BOM,現在一些編輯軟件,可以在保存為UTF-8編碼時可以選擇是否帶
BOM保存。
對於PHP文件,在使用UTF-8編碼時,最好都不要BOM保存。因為當你使用include/require/include_once/require_once這些函數去包含一個帶BOM的文件時,你得到的網頁,在某些兼容性
不是很好的瀏覽器下,你會發現你的網頁的實際顯示效果跟預期的有細微的差別。