1. 程式人生 > >PHP 生成 csv 檔案時亂碼解決

PHP 生成 csv 檔案時亂碼解決

今天處理PHP匯出資料時遇到了亂碼問題,下載的程式檔案為utf-8編碼,下載下來的csv檔案用編輯器開啟也是utf-8編碼,但直接用excel開啟時確顯示亂碼。後來從網上找到一篇文章得以解決,在此儲存。
原文章地址為:http://www.haoguoliang.com/blog/2009/07/linux-php-csv.html
解決php匯出csv檔案開啟亂碼郝國樑 (2009年7月28日 11:57) | 暫無評論 | 暫無引用通告 
什麼是CSV檔案?Comma Separator Value(逗號分隔值)是也。常常用來資料轉換的中間檔案存在,比如:從Mysql中匯出資料到CSV,匯入CSV到SqlServer中。最近在用Epsilon的郵件服務做郵件營銷,Epsilon的web前端接受

csv格式的郵件列表,於是乎在Linux下用PHP指令碼從Mysql資料庫中將user表的資料按照條件匯出成csv,以便匯入到Epsilon的web前端發郵件,問題出現了,使用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),具體的對應關係見下表。

BytesEncoding Form00 00 FE FFUTF-32, big-endianFF FE 00 00UTF-32, little-endianFE FFUTF-16, big-endianFF FEUTF-16, little-endianEF BB BFUTF-8
類Unix系統中並沒有使用 BOM,因為它會破壞現有的 ASCII 檔案的語法約定。
我的php原始碼檔案是用NotePad++生成的,在Centos下執行,格式為:以UTF-8無BOM格式編碼,因此要想匯出Microsoft Excel可以正常顯示的UTF-8的CSV檔案,需要顯式的輸出BOM(EF BB BF,上表的最後一種型別),然後再
輸出Mysql中的有效資料。編寫如下函式:
<?php
/**
* @param $file_name string 要匯出的檔名,比如:mail-list.csv
* @param $content string 要輸出csv格式的資料,用逗號分隔各欄位
* @return null
*/
function output_csv($file_name,$content)
{
$content = "\xEF\xBB\xBF".$content; //新增BOM
if( empty( $file_name ) ) 
{
$file_name = date("Ymd")."csv";
}
header( "Cache-Control: public" );
header( "Pragma: public" );
header( "Content-type: text/csv" ) ;
header( "Content-Dis; filename={$file_name}" ) ;
header( "Content-Length: ". strlen( $content ) );
echo $content;
exit; 
}
?>
問題解決。
PS1:output_csv函式使用前,確保php原始碼是utf-8,並且無BOM,並且沒有輸出任何內容。
PS2:BOM實際上挺煩人,如果你的網頁(*.html)有BOM,在IE6.x下面開啟會發現一神奇的空行,Firefox下卻沒有,遇到過沒?
PS3:參考文章UTF-8,UTF-16,UTF-32,BOM
相關php圖書: