微軟在 UTF-8 中使用 BOM 是因爲這樣可以把 UTF-8 和 ASCII 等編碼明白區分開。
不然用Excel打開CSV文件有多是亂碼的
演示樣例代碼例如如下:
response.setContentType("text/csv");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setCharacterEncoding("UTF-8");
byte[] uft8bom={(byte)0xef,(byte)0xbb,(byte)0xbf};
OutputStream out = response.getOutputStream();
out.write(uft8bom);
OutputStreamWriter writer = new OutputStreamWriter(out,"UTF-8");
//write other content ...
什麼是BOM:
BOM(byte-order mark),即字節順序標記,它是插入到以UTF-八、UTF16或UTF-32編碼Unicode文件開頭的特殊標記,用來識別Unicode文件的編碼類型。對於UTF-8來講,BOM並不是必須的。因爲BOM是用來標記多字節編碼文件的編碼類型和字節順序(big-endian或little- endian)。php
而UTF8中,每個字符的編碼有多少位是經過第一個字節來表述的。而且沒有big-endian和little-endian的區分,見後述。
BOMs 文件頭:
00 00 FE FF = UTF-32, big-endian
FF FE 00 00 = UTF-32, little-endian
EF BB BF = UTF-8,
FE FF = UTF-16, big-endian
FF FE = UTF-16, little-endian
另外一個要注意的是:UTF-8 的網頁代碼不該使用 BOM。不然常常會出錯:
在網頁上使用BOM是個錯誤。windows
BOM設計出來不是用來支持HTML和XML的。要識別文本編碼,HTML有charset屬性,XML有encoding屬性,不是必需拉BOM撐場面。儘管理論上BOM可以用來識別UTF-16編碼的HTML頁面,但實際project上很是少有人這麼幹。畢竟UTF-16這樣的編碼連ASCII都雙字節,實在不適用於作網頁。
Windows使用BOM的歷史緣由:
一般BOM是用來標示Unicode純文本字節流的,用來提供一種方便的方法讓文本處理程序識別讀入的.txt文件是哪一個Unicode編碼(UTF-8。UTF-16BE,UTF-16LE)。post
Windows相對對BOM處理比較好,是因爲Windows把Unicode識別代碼集成進了API裏。主要是CreateFile()。打開文本文件時它會本身主動識別並剔除BOM。編碼
Windows用這個有歷史緣由,因爲它最初脫胎於多代碼頁的環境。而引入Unicode時Windows的設計者又但願能在用戶不注意的狀況下同一時候兼容Unicode和非Unicode(Multiple byte)文本文件,就僅僅能借助這樣的小trick了。設計
帶BOM的文本文件在Linux/unix環境又常常會遇到問題:
知乎介紹的很是具體:
http://www.zhihu.com/question/20167122
文本文件解析:
文本文件相應於人類可以閱讀的文本,怎樣從2進制轉換爲文本文件呢?起初因爲計算機在美國發明。天然你們考慮的是英語怎樣表示,英語字母總共26個。加上特殊字符,128個字符,7位既一個byte就能夠表示出來。這個就是你們所熟知的ascill編碼。unix
相應關係很是easy,一個字符相應一一個byte。code
但很是快發現。其它非英語國家的文字遠遠超過ascill碼,這時候你們固然想統一一下。不一樣國家出了本身不一樣的編碼方式。中國的gb2312就是本身作出來的編碼方式,這樣下去每個國家都有本身的編碼方式,來回轉換太麻煩了。這時候出現了新的編碼方式,unicode編碼方式,想將編碼統一,因此規定了每個字符相應的unicode碼。 一、很是多文件都是ascii編碼,假設用unicode 太浪費。ip
二、沒有標誌位說明該幾個字節來解析爲一個符號。 這時候解救世界的utf出現了。utf是unicode的一種實現,僅僅只是更聰明瞭。utf16是佔用兩字節,或者四字節。utf32是佔用四字節。utf-8
utf8是很是聰明的一種表示方式。ci
一、對於單字節符號,字節第一位爲0,後面7位表示字節編碼。
二、對於n字節符號,第一字節的前n位都設爲1,第n+1位爲0。其他位用於編碼。
對於不一樣的編碼,在文本的最前方有不一樣的標誌,unicode 一般有兩位來表示各自是ff fe, 或者feff, fffe表示litte-endian 編碼feff表示big-endian編碼。
utf8是efbbbf來開頭的。
可以看出來utf-8是自解釋的。因此不用帶這個標誌文件,大多數程序是可以識別的。
但有些程序不能識別這個標誌,比方php就會直接把這個標誌當文本解析,不會忽略。