php fwrite寫入文件bom頭導致的亂碼問題解決


 

最近導出文件遇到fwrite導出亂碼,而且中英文都亂碼,很費解。折騰了一番之后終於找到問題所在了,mark下。

UTF-8 BOM 又叫 UTF-8 簽名,其實 UTF-8 的 BOM 對 UFT-8 沒有作用,是為了支援 UTF-16,UTF-32 才加上的 BOM ,BOM 簽名的意思就是告訴弱編輯器(記事本)當前文件采用何種編碼,方便編輯器識別。

PHP 在設計之初,沒有考慮到 BOM 頭的問題,因此很容易因為 BOM 頭引發詭異的問題,比如編碼轉換失敗,樣式錯亂等等問題,而且此問題相當隱蔽,很難確定發生問題的文件(試想在沒有工具的情況下從上萬的工程文件中找到哪個文件帶有 BOM 頭)。

BOM 頭是隱藏字符,非編輯字符,就像普通空文件一樣,當我們寫 <?php 的時候其實之前已經加了 BOM 頭,如下(file.php):

{BOM頭}<?php

.....
當 file.php 被其他文件包含時,由於 BOM 頭在 php 標簽外,會當作輸出內容輸出到瀏覽器,然后引發問題。

少年,珍愛生命,遠離 BOM 。

php fwrite輸出也遇到了這個問題,判斷是否有bom,如果沒有加手動加上bom字符串,如果有直接輸出,問題解決。

代碼如下:

 

 1 function checkBOM($filename)
 2 {
 3     if (!file_exists($filename)) {
 4         return FALSE;
 5     }
 6     $contents   = file_get_contents($filename);
 7     $charset[1] = substr($contents, 0, 1);
 8     $charset[2] = substr($contents, 1, 1);
 9     $charset[3] = substr($contents, 2, 1);
10     if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
11         return TRUE;
12     }
13     return FALSE;
14 }
15 
16 $msg = "你好\n";
17 //如果默認編碼不是utf8,先用函數utf8_encode將所需寫入的數據變成UTF編碼格式。
18 //$msg = utf8_encode($msg);
19 //$msg = iconv('gbk', 'utf-8', $msg);
20 
21 $fileName = 'test';
22 $filePath = './test.txt';
23 $checkBom = checkBOM($filePath);
24 // 有bom的情況下"\xEF\xBB\xBF"第一次寫入這段字符不可缺少
25 if ($checkBom == FALSE) {
26     $msg = "\xEF\xBB\xBF" . $msg;
27 }
28 $fp = @fopen($filePath, 'a');
29 @fwrite($fp, $msg);
30 @fclose($fp);

 

function checkBOM($filename)
{
if (!file_exists($filename)) {
return FALSE;
}
$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) {
return TRUE;
}
return FALSE;
}

$msg = "你好\n";
//如果默認編碼不是utf8,先用函數utf8_encode將所需寫入的數據變成UTF編碼格式。
//$msg = utf8_encode($msg);
//$msg = iconv('gbk', 'utf-8', $msg);

$fileName = 'test';
$filePath = './test.txt';
$checkBom = checkBOM($filePath);
// 有bom的情況下"\xEF\xBB\xBF"第一次寫入這段字符不可缺少
if ($checkBom == FALSE) {
$msg = "\xEF\xBB\xBF" . $msg;
}
$fp = @fopen($filePath, 'a');
@fwrite($fp, $msg);
@fclose($fp);


不知道有沒有更好的辦法,歡迎交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM