CSV乱码 - UTF-8 Unicode (with BOM)
Unicode
統(tǒng)一碼,也叫萬(wàn)國(guó)碼、單一碼(Unicode)是計(jì)算機(jī)科學(xué)領(lǐng)域里的一項(xiàng)業(yè)界標(biāo)準(zhǔn),包括字符集、編碼方案等。Unicode 是為了解決傳統(tǒng)的字符編碼方案的局限而產(chǎn)生的,它為每種語(yǔ)言中的每個(gè)字符設(shè)定了統(tǒng)一并且唯一的二進(jìn)制編碼,以滿足跨語(yǔ)言、跨平臺(tái)進(jìn)行文本轉(zhuǎn)換、處理的要求。
如果把各種文字編碼形容為各地的方言,那么Unicode就是世界各國(guó)合作開發(fā)的一種語(yǔ)言。
在這種語(yǔ)言環(huán)境下,不會(huì)再有語(yǔ)言的編碼沖突,在同屏下,可以顯示任何語(yǔ)言的內(nèi)容,這就是Unicode的最大好處。 就是將世界上所有的文字用2個(gè)字節(jié)統(tǒng)一進(jìn)行編碼。那樣,像這樣統(tǒng)一編碼,2個(gè)字節(jié)就已經(jīng)足夠容納世界上所有的語(yǔ)言的大部分文字了。
Unicode的學(xué)名是"Universal Multiple-Octet Coded Character Set",通用多八位編碼字符集,簡(jiǎn)稱為UCS。
現(xiàn)在用的是UCS-2,即2個(gè)字節(jié)編碼,而UCS-4是為了防止將來(lái)2個(gè)字節(jié)不夠用才開發(fā)的。
BOM
在UCS 編碼中有一個(gè)叫做 “Zero Width No-Break Space” ,中文譯名作“零寬無(wú)間斷間隔”的字符,它的編碼是 FEFF。而 FEFF 在 UCS 中是不存在的字符,所以不應(yīng)該出現(xiàn)在實(shí)際傳輸中。UCS 規(guī)范建議我們?cè)趥鬏斪止?jié)流前,先傳輸字符 “Zero Width No-Break Space”。這樣如果接收者收到 FEFF,就表明這個(gè)字節(jié)流是 Big-Endian 的;如果收到FFFE,就表明這個(gè)字節(jié)流是 Little- Endian 的。因此字符 “Zero Width No-Break Space” (“零寬無(wú)間斷間隔”)又被稱作 BOM。
UTF-8
UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是針對(duì)Unicode的一種可變長(zhǎng)度字符編碼。它可以用來(lái)表示Unicode標(biāo)準(zhǔn)中的任何字符,而且其編碼中的第一個(gè)字節(jié)仍與ASCII相容,使得原來(lái)處理ASCII字符的軟件無(wú)須或只進(jìn)行少部分修改后,便可繼續(xù)使用。因此,它逐漸成為電子郵件、網(wǎng)頁(yè)及其他存儲(chǔ)或傳送文字的應(yīng)用中,優(yōu)先采用的編碼。
UTF-8 BOM
UTF-8 不需要 BOM 來(lái)表明字節(jié)順序,但可以用 BOM 來(lái)表明編碼方式。字符 “Zero Width No-Break Space” 的 UTF-8 編碼是 EF BB BF。所以如果接收者收到以 EF BB BF 開頭的字節(jié)流,就知道這是 UTF-8編碼了。Windows 就是使用 BOM 來(lái)標(biāo)記文本文件的編碼方式的。
CSV文件亂碼問(wèn)題
類似WINDOWS自帶的記事本等軟件,在保存一個(gè)以UTF-8編碼的文件時(shí),會(huì)在文件開始的地方插入U(xiǎn)TF-8 BOM頭。記事本等編輯器通過(guò)它來(lái)識(shí)別這個(gè)文件是否以UTF-8編碼(當(dāng)然即便沒有UTF-8 BOM頭記事本也能通過(guò)其它方式正確識(shí)別UTF-8編碼)。
如果一個(gè)UTF-8編碼的字符串的開頭處沒有BOM頭又會(huì)發(fā)生什么?
舉個(gè)例子
代碼demo
/*** csv 寫入文件頭** @param pathAndName 文件全路徑名* /Users/yangcheng/Documents/dkangel.csv* @throws IOException IO異常,上層捕獲處理*/private static void addHeadToTmpCsv(String pathAndName) throws IOException {FileOutputStream outputStream = new FileOutputStream(pathAndName, true);try (OutputStreamWriter streamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);BufferedWriter writer = new BufferedWriter(streamWriter)) {writer.write("姓名,年齡,性別");writer.newLine();writer.write("dkangel,25,男");writer.newLine();writer.write("張三,30,男");writer.flush();} finally {outputStream.close();}}public static void main(String[] args) {String path = "/Users/yangcheng/Documents/dkangel.csv";try {addHeadToTmpCsv(path);} catch (IOException e) {e.printStackTrace();}}運(yùn)行結(jié)果
可以通過(guò)Java代碼生成csv文件,未指定bom標(biāo)識(shí),使用excel查看的時(shí)候中文亂碼了
文件頭添加bom標(biāo)識(shí)
private static void addHeadToTmpCsv(String pathAndName) throws IOException {FileOutputStream outputStream = new FileOutputStream(pathAndName, true);// 追加BOM標(biāo)識(shí)outputStream.write(0xef);outputStream.write(0xbb);outputStream.write(0xbf);// 或者 writer.write('\uFEFF');......}運(yùn)行結(jié)果
總結(jié)
Excel打開沒有BOM頭的csv文件時(shí)會(huì)出現(xiàn)亂碼問(wèn)題,添加bom標(biāo)識(shí)后亂碼問(wèn)題解決
注意
bom標(biāo)識(shí)只用添加一次,那就是文件頭的位置。如果在數(shù)據(jù)行頭部添加bom標(biāo)識(shí)則單元格數(shù)據(jù)前會(huì)多一個(gè)空格出來(lái),可以通過(guò)WPS提示看出。
附錄
參考
? unicode:https://baike.baidu.com/item/%E7%BB%9F%E4%B8%80%E7%A0%81/2985798?fromtitle=Unicode&fromid=750500
? bom:https://baike.baidu.com/item/BOM/2790364
? utf-8:https://baike.baidu.com/item/UTF-8/481798
總結(jié)
以上是生活随笔為你收集整理的CSV乱码 - UTF-8 Unicode (with BOM)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用transform制作书本翻页效果
- 下一篇: CVSS评分策略分析及近年来满分漏洞盘点