最近在vue导入csv文件踩的一个坑,废话就不多说了,直接上源码和处理过程。
过程:我最近使用js-xlsx导入CSV文件时会出现中文乱码,其实这种问题基本上都是因为文件的编码不对造成的,因为使用这个插件用的比较多之前是可以直接使用UTF-8格式的csv文件导入的,但没想到还是出现了文件格式问题
这个是非UTF-8格式的,
这个是UTF-8格式的
然后,我们打开 https://oss.sheetjs.com/js-xlsx/ 测试下导入这个文件的结果
源代码:
export function export_excel_to_json(evt) {//读取方法
var wb; //读取完成的数据
var rABS = false; //是否将文件读取为二进制字符串
var isCSV;
if(!evt.target.files) {
return;
}
var f = evt.target.files[0];
var reader = new FileReader();
var pet = new Promise(function(resolve, reject) {
reader.onload = function(e) {
var data = e.target.result;
var XLSX = require('xlsx');
wb = null;
if(isCSV) {
data = new Uint8Array(data);
let f = isUTF8(data);
//console.log("是CSV文件,编码" + (f ? "是" : "不是") + "UTF-8");
if(f) {
data = e.target.result;
} else {
var str = cptable.utils.decode(936, data);
wb = XLSX.read(str, {
type: "string"
});
}
} else {
//console.log("不是CSV文件");
}
if(!wb) {
wb = rABS || isCSV ? XLSX.read(btoa(fixdata(data)), {
type: 'base64'
}) : XLSX.read(data, {
type: 'binary'
});
}
//console.log(wb);
//wb.SheetNames[0]是获取Sheets中第一个Sheet的名字
//wb.Sheets[Sheet名]获取第一个Sheet的数据
//console.log(JSON.stringify( XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]) ));
var result = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
resolve(result);
}
isCSV = f.name.split(".").reverse()[0] == "csv"; //判断是否是 CSV
if(rABS || isCSV) {
reader.readAsArrayBuffer(f);
} else {
reader.readAsBinaryString(f);
}
evt.value = "";
}).catch(error => console.log(error));
//console.log(pet);
return pet;
}
function fixdata(data) { //文件流转BinaryString
var o = "",
l = 0,
w = 10240;
iconv.skipDecodeWarning = true;
let str = iconv.encode(o, 'utf-8');
for(; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)));
o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)));
return o;
}
我使用了https://github.com/wayfind/is-utf8/blob/master/is-utf8.js来处理这个问题
isUTF8.js
function isUTF8(bytes) { //非中文格式CSV文件转换UTF-8方法
var i = 0;
while(i < bytes.length) {
if(( // ASCII
bytes[i] == 0x09 ||
bytes[i] == 0x0A ||
bytes[i] == 0x0D ||
(0x20 <= bytes[i] && bytes[i] <= 0x7E)
)) {
i += 1;
continue;
}
if(( // non-overlong 2-byte
(0xC2 <= bytes[i] && bytes[i] <= 0xDF) &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF)
)) {
i += 2;
continue;
}
if(( // excluding overlongs
bytes[i] == 0xE0 &&
(0xA0 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
) ||
( // straight 3-byte
((0xE1 <= bytes[i] && bytes[i] <= 0xEC) ||
bytes[i] == 0xEE ||
bytes[i] == 0xEF) &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
) ||
( // excluding surrogates
bytes[i] == 0xED &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x9F) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
)
) {
i += 3;
continue;
}
if(( // planes 1-3
bytes[i] == 0xF0 &&
(0x90 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
) ||
( // planes 4-15
(0xF1 <= bytes[i] && bytes[i] <= 0xF3) &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
) ||
( // plane 16
bytes[i] == 0xF4 &&
(0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x8F) &&
(0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
(0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
)
) {
i += 4;
continue;
}
return false;
}
return true;
}
感谢这位老哥的解决方法https://www.jianshu.com/p/439fbc4a11a8