最近在做的一個網站發生了一個很詭異的BUG:
接下來排查錯誤:
一開始以為是CSS樣式中的:before語句對頁面元素有了影響,但是:before僅對body元素進行了設定,僅僅只是增加了一個元素,不會造成如此多的元素的間隔距離都拉開了的效果;且在刪除:before語句後瀏覽,問題依然存在。因此排除了這個可能性。
然後開始仔細的檢查(過程很痛苦),發現這些出問題的地方都有一個共同點:因為網站是採用靜態化實現,使用了伺服器端的靜態包含,而每個多餘的行都出現在每個包含檔案(<!--#include virtual="**.inc" -->)的前面。於是去看包含檔案的產生過程,去掉檔案產生時頭尾可能產生的分行符號和空白串。但是更新程式後,重建靜態檔案,問題仍然存在。
後來實在找不到問題所在,只能先放一下去完成其他的功能。但是,這個沒有解決的問題,一直縈繞在我的心頭,時時都能想起它,時時都在想“為什麼呢”?如鯁在喉,無法下咽。總覺得有什麼事情沒做完一樣,做其他的事情時感覺也不踏實。
因為基本確認是包含檔案出現了問題,於是集中在檔案產生和包含這一塊進行排除。在做其他事的時候無意中想到檔案編碼這一塊的事情,於是就想會不會是這個因素的影響。於是上網搜尋,發現了如下幾篇文章:
1、什麼是BOM頭
2、解釋BOM頭和去掉方法
3、XML的BOM
看完後,隱約覺得應該是找到問題所在了;於是看了看自己程式,發現在產生靜態檔案時,採用了UTF-8編碼來設定位元組流,同時在儲存到檔案時也採用了UTF-8編碼,代碼如下:
File.WriteAllText(Task.FullPath + filename + Task.Extension, content, Encoding.UTF8);
於是決定首先利用UE去除BOM頭試試效果:開啟某一個靜態化後的inc檔案,另存新檔時選擇“UTF-8 無 BOM”,能BOM頭。如:
儲存檔案後再進行瀏覽,問題不再出現。從而確定了BOM頭在一些瀏覽器內解析時,會被解析為一個空行或者一個區塊層級元素。在用程式儲存檔案時,如果指定了檔案的編碼格式為UTF-8,也會為檔案增加BOM頭。
因此組建檔案時,改為去掉檔案儲存時指定的UTF-8編碼,但位元組流仍採用UTF-8編碼處理。
content = Encoding.UTF8.GetString(bytes);File.WriteAllText(Task.FullPath + filename + Task.Extension, content);
同時因為位元組流採用UTF-8編碼,在html頁面裡需要指定頁面的編碼方式,不然會出現亂碼:
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
做完以上處理,再次重建所有inc檔案後,在不同瀏覽器下重新整理查看,發現問題均得到解決。
在確認了BUG的原因並最終解決了問題之後,居然找到了這樣一篇文章:關於shtml頁面include問題解決方案因為utf-8的BOM頭引起的出現一個空行 !!為什麼總是在費盡九牛二虎之力解決問題後,才發現這麼一篇能精確指導問題的解決方案的文章呢?
另外,推薦一個關於編碼方面的文章:由web程式出現亂碼開始挖掘(Bom頭、字元集與亂碼)
做程式開發,確實是知道得越多,知道的就越少。坑太多啊。絕逼的學無止盡。