天天看點

bom csv java_JAVA導出CSV亂碼問題

背景

我在項目中使用阿裡雲OSS存儲檔案,導出時導出為csv格式的檔案。然而打開時總是存在中文亂碼。

通過網上的一番搜尋,大抵是使用記事本先打開csv檔案,然後再儲存為ANSI格式,然後再用excel打開時就不存在亂碼了。但這不是程式裡的解決方式,我們不可能提供一個半成品的導出檔案供使用者使用。經過一番網上搜尋,發現問題的根源在于UTF8的BOM資訊頭。

本來UTF8是不需要BOM頭的,這就不得不說到微軟的可惡了。

BOM簡介

BOM中文譯作”位元組順序标記”,UTF8本不需要BOM來表明位元組順序,但WINDOWS用BOM來标記檔案檔案的編碼方式。BOM的UTF8編碼是”EF BB BF”,是以如果接收者收到以”EF BB BF”開頭的位元組流,就知道這是UTF8編碼了。WINDOWS系軟體儲存的UTF8編碼的檔案需要檔案的開頭保有這個BOM字元。

問題解決

項目中使用OSS存儲檔案,存儲成功後傳回一個簽名過的檔案url位址,前端再根據這個url去請求擷取檔案。由于前端是直接使用”window.open(url)”的方式,直接新開視窗通路連結,下載下傳下來的檔案預設是UTF8編碼的,是以使用excel打開時需要BOM字元來表明是UTF8編碼,否則其中的中文則會産生亂碼。

是以,在OSS存儲時,我們就需要額外添加BOM頭一并存儲。代碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17OSSClient client = new OSSClient(ossHelper.getEndPoint(), ossHelper.getAccessKeyId(),

ossHelper.getAccessKeySecret());

ObjectMetadata objectMetadata = new ObjectMetadata();

objectMetadata.setContentType("application/vnd.ms-excel");

objectMetadata.setContentEncoding("UTF-8");

objectMetadata.setContentDisposition("attachment; filename=" + fileName + ".csv");

// 增加BOM頭資訊

String bom = new String(new byte[] { (byte) 0xEF, (byte) 0xBB,(byte) 0xBF });

try {

// 以同樣的編碼擷取位元組流

client.putObject(ossHelper.getBucketName(), fileName,

new ByteArrayInputStream((bom + exportFileString).getBytes("UTF-8")), objectMetadata);

}catch (UnsupportedEncodingException e){

e.printStackTrace();

}