這篇本來只是單純的網頁匯出EXCEL
但因為遇到了匯出的內容亂碼,異外的認識了BOM的故事.
匯出很簡單,就是用....
但是在匯出的時侯,沒有BOM的檔案,會讓EXCEL不知道要用utf8來解析它,所以EXCEL呈現亂碼了.(疑?那它用什麼解析的呢?
不知道為什麼只導出GridView,但整個頁面都輸出了.所以只好把不要的區塊visible=false
public void ExportToEXCEL(System.Web.UI.WebControls.GridView gv, string filename, string headtxt)
{
this.dgShow.AllowPaging = false;
this.dgShow.EnableViewState = false; //把ViewState給關了
this.dgShow.DataBind();
plQuery.Visible = false;Response.Buffer = true; Response.Charset = "UTF-8"; //設定字集 Response.AppendHeader("Content-Disposition", "attachment;filename=xxx.xls"); //filename 可自定 Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8"); Response.ContentType = "application/ms-excel "; //內容型態設為Excel System.IO.StringWriter objStringWriter = new System.IO.StringWriter(); System.Web.UI.HtmlTextWriter objHtmlTextWriter = new System.Web.UI.HtmlTextWriter(objStringWriter); //this.RenderControl(objHtmlTextWriter); this.dgShow.RenderControl(objHtmlTextWriter); //不知道為什麼只導出dgshow,但整個頁面都輸出了.所以只好把不要的區塊visible=false Response.Write(objStringWriter.ToString()); Response.End(); this.dgShow.AllowPaging = true; this.dgShow.EnableViewState = true; //把ViewState this.dgShow.DataBind(); plQuery.Visible = true; } public override void VerifyRenderingInServerForm(Control control) { // '處理'GridView' 的控制項 'GridView' 必須置於有 runat=server 的表單標記之中 }
Response.ClearContent();
Response.Clear();
Response.Buffer=true;
Response.Charset ="UTF-8"; //設定字集
Response.ContentEncoding = System.Text.Encoding.UTF8;//表格內容新增編碼格式string sFilename = HttpUtility.UrlEncode("中文", System.Text.Encoding.UTF8);//處理中文檔名亂碼 Response.AppendHeader("Content-Disposition","attachment;filename="+sFilename+".xls"); Response.ContentType = "application/ms-excel "; //內容型態設為Excel this.EnableViewState = false; //把ViewState給關了 System.IO.StringWriter objStringWriter = new System.IO.StringWriter(); System.Web.UI.HtmlTextWriter objHtmlTextWriter = new System.Web.UI.HtmlTextWriter(objStringWriter); this.DataGrid1.RenderControl(objHtmlTextWriter); //get畫面上的資料 System.IO.StreamWriter sw = new System.IO.StreamWriter( Response.OutputStream,System.Text.Encoding.UTF8);//這樣一筆的時侯,就不會亂碼了 sw.Write(objStringWriter.ToString()); sw.Close(); Response.End();
匯出的EXCEL檔案,如果很多筆,OK.但如果只有一筆,就會有中文亂碼的情況
解決方法,使用stream寫入,且指定UFT8.就可以了.
ref
https://blog.darkthread.net/blog/csv-encoding-again/
BOM
位元組順序記號(英語:byte-order mark,BOM)是位於碼點U+FEFF的統一碼字元的名稱。當以UTF-16或UTF-32來將UCS/統一碼字元所組成的字串編碼時,這個字元被用來標示其位元組序。它常被用來當做標示檔案是以UTF-8、UTF-16或UTF-32編碼的記號。資料擷取自維基百科
哈.有聽沒有懂.
目前已知
軟體 | BOM | 沒BOM |
---|---|---|
記事本 | OK | OK |
EXCEL | OK | 亂碼 |
狀態 | File.WriteAllText | StreamWriter | memo |
---|---|---|---|
沒指定 | 沒BOM | 沒BOM | File.WriteAllText("B:\F1.csv", '中文'); |
指定但不想有BOM | -- | -- | new StreamWriter (strPath,false,utf8); |
指定 | 有BOM | 有BOM | File.WriteAllText("B:\F1.csv", '中文', Encoding.UTF8); |
ref
https://blog.darkthread.net/blog/write-utf8-file-with-bom/
class | about BOM | about Encoding |
---|---|---|
StreamWriter | 寫的時侯, 會把BOM加進來 | 預設會先自動判斷檔案編碼,無法確認才會使用設定的編碼 |
StreamReader | 讀的時侯, 會把BOM自動濾掉 |
Windows 作業系統不少程式(像是記事本),預設會對 UTF-8 檔案加上 BOM
而 Linux 則避免妨礙到像是解譯器腳本而不加 BOM,對於沒有預期要處理 BOM 的 Linux 程式而言,會造成讀取錯誤,這也是跨平台常遇到的事情之一。6
StreamReader 預設會先自動判斷檔案編碼,無法確認才會使用設定的編碼。
所以如果不需要BOM的話,不指定也沒關係.
先介紹3種編碼,介紹的好清楚.
再介紹為什麼需要BOM.
再介紹萬惡的BOM是怎麼回事.
https://ignatius1895.pixnet.net/blog/post/71034743-%E5%AD%97%E5%85%83%E7%B7%A8%E7%A2%BC%E8%88%87%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%28%E4%BA%94%29%EF%BC%9Aunicode%E7%9A%84%E7%B7%A8%E7%A2%BC