出現亂碼的源代碼:
with open('收盤價Dashboard.html','w',encoding='utf-8') as html_file:
html_file.write('<html><head><title>收盤價Dashboard</title><metacharset="utf-8"></head><body>\n')
for svg in ['收盤價折線圖(¥).svg','收盤價對數變換折線圖(¥).svg','收盤價月日均值(¥).svg','收盤價周日均值(¥).svg','收盤價星期均值(¥).svg']:
html_file.write('<object type="image/svg+xml" data="{0}" height=500></object>\n'.format(svg))
html_file.write('</body></html>')
将 with open('收盤價Dashboard.html','w',encoding='utf-8') as html_file:
改為 with open('收盤價Dashboard.html','w',encoding='utf-8-sig') as html_file: 即可解決亂碼問題。
原理:簡單的說,utf-8-sig是對位元組編碼有序的。
UTF-8以位元組為編碼單元,它的位元組順序在所有系統中都是一様的,沒有位元組序的問題,也是以它實際上并不需要BOM(“ByteOrder Mark”)。但是UTF-8 with BOM即utf-8-sig需要提供BOM。
簡介
BOM —— Byte Order Mark,中文名譯作“位元組順序标記”。在這裡找到一段關于 BOM 的說明:
在UCS 編碼中有一個叫做 "Zero Width No-Break Space" ,中文譯名作“零寬無間斷間隔”的字元,它的編碼是 FEFF。而 FFFE 在 UCS 中是不存在的字元,是以不應該出現在實際傳輸中。UCS 規範建議我們在傳輸位元組流前,先傳輸字元 "Zero Width No-Break Space"。這樣如果接收者收到 FEFF,就表明這個位元組流是 Big-Endian 的;如果收到FFFE,就表明這個位元組流是 Little- Endian 的。是以字元 "Zero Width No-Break Space" (“零寬無間斷間隔”)又被稱作 BOM。
UTF-8 不需要 BOM 來表明位元組順序,但可以用 BOM 來表明編碼方式。字元 "Zero Width No-Break Space" 的 UTF-8 編碼是 EF BB BF。是以如果接收者收到以 EF BB BF 開頭的位元組流,就知道這是 UTF-8編碼了。Windows 就是使用 BOM 來标記文本檔案的編碼方式的。
字元U+FEFF如果出現在位元組流的開頭,則用來辨別該位元組流的位元組序,是高位在前還是低位在前。如果它出現在位元組流的中間,則表達零寬度非換行空格的意義,使用者看起來就是一個空格。從Unicode3.2開始,U+FEFF隻能出現在位元組流的開頭,隻能用于辨別位元組序,就如它的名稱——位元組序标記——所表示的一樣;除此以外的用法已被舍棄。取而代之的是,使用U+2060來表達零寬度無斷空白。
類似WINDOWS自帶的記事本等軟體,在儲存一個以UTF-8編碼的檔案時,會在檔案開始的地方插入三個不可見的字元(0xEF 0xBB 0xBF,即BOM)。它是一串隐藏的字元,用于讓記事本等編輯器識别這個檔案是否以UTF-8編碼。對于一般的檔案,這樣并不會産生什麼麻煩。但對于 PHP來說,BOM是個大麻煩。
PHP并不會忽略BOM,是以在讀取、包含或者引用這些檔案時,會把BOM作為該檔案開頭正文的一部分。根據嵌入式語言的特點,這串字元将被直接執行(顯示)出來。由此造成即使頁面的 top padding 設定為0,也無法讓整個網頁緊貼浏覽器頂部,因為在html一開頭有這3個字元呢!