发现问题
在MacOS开发时,导出_.csv文件时,在WPS打开时正常,但是在Office Excel打开会乱码,可使用如下代码模拟_.csv文件下载
const a = document.createElement('a');
a.href = 'data:text/csv,学号,语文,数学,物理\n10,20,30,40\n50,60,70,80';
a.download = 'test.csv';
a.innerText = '点击我下载';
document.body.append(a);
寻找原因
经过Google所得
- Office Excel在读取*.csv文件时,是通过读取该文件的BOM来识别编码,如果该文件不存在BOM,则会按照默认编码解读,会出现乱码
- 在上述步骤导出CSV时,未在头部添加BOM
许多视窗程序(包含记事本)会需要添加字节顺序标记到UTF-8文件,否则将无法正确解析编码,而出现乱码。
由以上原因,导致了Office Excel 读取该文件时编码不一致,从而导致了乱码
解决
既然是由于BOM导致的问题,那么加上BOM就好了
const a = document.createElement('a');
a.href = 'data:text/csv,\uFEFF学号,语文,数学,物理\n10,20,30,40\n50,60,70,80';
a.download = 'test.csv';
a.innerText = '点击我下载';
document.body.append(a);
BOM
什么是BOM
BOM:此BOM非彼BOM,这里的BOM不是指浏览器对象模型,而是指的是 Byte Order Mark(字节序)
大端序和小端序
BOM分为两个顺序,大端序、小端序,下面拿一个例子来解释,"我"的码点为 25105,转为16进制为 0x6211
大端序:高位字节在前,0x62在前,0x11在后,比较符合人类识别,例如阿拉伯数字100,我们习惯高位在前
小端序:高位字节在后,0x11在前,0x62在后
计算机在读取数据的时候,是按照一个字节一个字节读取,假设存储顺序为 [0x62, 0x11],此时如果计算机按照大端序解析,则得到 "我",反之得得到 "ᅢ"
以下是常用的BOM
| 编码 | BOM表示 |
|---|---|
| UTF-8 | EF BB BF |
| UTF-16(大端序) | FE FF |
| UTF-16(小端序) | FF FE |
| UTF-32(大端序) | 00 00 FE FF |
| UTF-32(小端序) | FF FE 00 00 |
为什么UTF-8不需要指出BOM
UTF-16需要两个字节存储,上文说道计算机是按照一个字节读取的,必然得要知道字节序,那为什么UTF-8不需要呢?这是由于UTF-8的存储方式有关
UTF-8存储为1-4个字节,那么它怎么知道到底这个字符占了几个字节?UTF-8使用第一字节前几位表示整个字节的长度,如下所示
1字节:0xxx xxxx
2字节:110x xxxx 10xx xxxx
3字节:1110 xxxx 10xx xxxx 10xx xxxx
4字节:1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
所以对于UTF-8来说,它的字节顺序已经定死了