程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP與Unicode簽名(BOM)

PHP與Unicode簽名(BOM)

編輯:關於PHP編程

在編寫或者修改用UTF-8編碼保存的PHP文件時,有時會莫名其妙出現一些問題:
1. 頁面顯示一個“锘”字,其他一片空白;
2. 不能登入或者不能登出;
3. 頁頂出現一條空白;
4. 頁頂出現錯誤警告;
5. 其它不正常的情況;
6. 生成的圖片浏覽器無法識別。
分析原因:
 文件以UTF-8編碼保存時,有兩種情情況:帶Unicode簽名(BOM)和不帶Unicode簽名。BOM信息是文件開頭的一串隱藏的字符,用於讓某些編輯器識別這是個UTF-8編碼的文件。

類似WINDOWS自帶的記事本等軟件,在保存一個以UTF-8編碼的文件時,會在文件開始的地方插入三個不可見的字符(0xEF 0xBB 0xBF,即BOM——Byte Order Mark)。它是一串隱藏的字符,用於讓記事本等編輯器識別這個文件是否以UTF-8編碼。對於一般的文件,這樣並不會產生什麼麻煩。

但對於 PHP來說,PHP在設計時就沒有考慮BOM的問題,不會忽略UTF-8編碼的文件開頭BOM的那三個字符,會把BOM作為該文件開頭正文的一部分。由於必須在<?或者<?php後面的代碼才會作為PHP代碼執行,所以將會造成在頁面上輸出這三個字符,顯示效果就要看浏覽器了,一般是一個空行或是一個亂碼。由於在html一開頭有這3個字符的存在,即使頁面的 top padding 設置為0,也無法讓整個網頁緊貼浏覽器頂部。由於受COOKIE送出機制的限制,在這些文件開頭已經有BOM的文件中,COOKIE無法送出(因為在 COOKIE送出前PHP已經送出了文件頭),所以登入和登出功能失效。一切依賴COOKIE、SESSION實現的功能全部無效。

解決辦法:

在編輯、更改任何文本文件時,請務必使用不會亂加BOM的編輯器。Linux下的編輯器應該都沒有這個問題。WINDOWS下,請勿使用記事本等編輯器。推薦的編輯器是:Editplus 2.12版本以上;EmEditor;UltraEdit(需要取消‘添加BOM’的相關選項);Dreamweaver(需要取消‘添加BOM’的相關選項)等。

對於已經添加了BOM的文件,要取消的話,可以用以上編輯器另存一次。(Editplus需要先另存為gb,再另存為UTF-8。)

ultraedit, editplus, notepad四個工具對UTF-8 的支持不相同,下面是對四個工具對UTF-8 支持的總結:
  UTF-8 BOM header: 是三個字符: EF BB BF。
  1. notepad
notepad 在保存時,選擇UTF-8 格式,會在文件頭寫上BOM header.
  2. editplus
文件保存時,選擇UTF-8 格式,不會在文件頭寫上 BOM header.
  3. ultraedit
ultraedit 對UTF-8 的支持最為完備。在advanced->configuration中可以 選擇文件保存時是否寫上BOM header.
  4. vi
指的是Linux 下的vim, 如果UTF-8 文件開頭有BOM header, 其能夠正常顯示UTF-8編碼,否則,顯示為亂碼。
  還有一些編碼轉換工具,比如,可以用java 寫一個簡單的編碼轉換工具,這些工具是不會增加BOM header的。

附錄:

UltreEdit的配置,將選項“保存時對所有UTF-8寫入UTF-8文件頭標記(BOM)”關閉。即:Write UTF-8 BOM header to ALL UTF-8 files when saved OFF。
不同版本有可能沒有,而要把“自動檢測utf8”關掉。這樣看utf8文件就亂碼了。
建議用editplus了。


檢測目錄下文件是否有BOM程序:
<?
//此文件用於快速測試UTF8編碼的文件是不是加了BOM,並可自動移除
//By Bob Shen

$basedir=".";; //修改此行為需要檢測的目錄,點表示當前目錄
$auto=0; //是否自動移除發現的BOM信息。1為是,0為否。

//以下不用改動

if ($dh = opendir($basedir)) {
while (($file = readdir($dh)) !== false) {
if ($file!='.' && $file!='..' && !is_dir($basedir."/".$file)) echo "filename: $file ".checkBOM("$basedir/$file")." <br>";
}
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);
}
?>

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved