1. 程式人生 > >php 生成csv mac下亂碼

php 生成csv mac下亂碼

<?php     $file_name = date('Ymd', time()) . '.csv'; //設定檔名     header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment;filename='.$file_name); header('Cache-Control: max-age=0'); $fp = fopen('php://output', 'a');
$row = [ 'name' => '測試'
, 'email' => 111111, 'mobile' => 22222, 'weixinid' => '微訊號', ]; fwrite($fp,"\xEF\xBB\xBF"); fputcsv($fp, $row);

php匯出csv檔案亂碼問題解決方法


說 這個問題之前首先來說一下什麼是CSV檔案?Comma Separator Value(逗號分隔值)是也。常常用來資料轉換的中間檔案存在,比如:從Mysql中匯出資料到CSV,匯入CSV到SqlServer中。在 Linux下用PHP指令碼從Mysql資料庫中將表的資料按照條件匯出成csv,使用utf-8編碼匯出CSV檔案,開啟后里邊的中文成了亂碼 (Windows下CSV檔案預設與Microsoft Excel關聯),用Notepad++或者Word開啟正常,不過排版很亂。原因:BOM惹的禍,微軟惹的禍。

什麼是BOM?Byte Order Mark(位元序標記)是也。

 

為 了識別 Unicode 檔案,Microsoft 建議所有的 Unicode 檔案應該以 ZERO WIDTH NOBREAK SPACE字元開頭。這作為一個”特徵符”或”位元組順序標記(byte-order mark,BOM)”來識別檔案中使用的編碼和位元組順序(big-endian或little-endian),具體的對應關係見下表。

Bytes Encoding Form
00 00 FE FFUTF-32, big-endian
FF FE 00 00UTF-32, little-endian
FE FFUTF-16, big-endian
FF FEUTF-16, little-endian
EF BB BFUTF-8

 
類Unix系統中並沒有使用 BOM,因為它會破壞現有的 ASCII 檔案的語法約定。

實現程式碼如果

注:在寫csv檔案時確保php原始碼是utf-8,並且無BOM,並且沒有輸出任何內容。

Excel在讀取csv的時候是通過讀取檔案頭上的bom來識別編碼的,如果檔案頭無bom資訊,則預設按照unicode編碼讀取。(這個bom是微軟自己定義的一種檔案頭部協定,顧名思義儲存在檔案頭部,儲存內容就是標識檔案編碼的資訊。)

而我們生成csv的平臺不一定遵循微軟的bom協議,導致如果輸出非unicode編碼的csv檔案(例如utf-8),並且沒有生成bom資訊的話,Excel自動按照unicode編碼讀取,就會出現亂碼問題了。

掌握了這點相信亂碼已經無法阻擋我們前進的步伐了:只需將非unicode編碼的csv檔案,用文字編輯器(推薦notepad++)開啟並轉換為帶bom的編碼形式(具體編碼方式隨意),問題解決。