由于网络的资源比较杂乱,自己看了并实践之后,总结一下
方法1: Input + FileReader 原生 API 的方式
首先通过input[type='file']输入框获取文件,然后通过浏览器提供的原生 File API 中的 FileReader 来读取本地文件。
代码如下
html
<input id="myFileInput" type="file" />
由于文件读取是异步的,我们需要在读取完成后获取到文件内容。因此,我们需要监听FileReader 对象的 load 事件,这个事件在文件读取完成后触发。
js
const read = () => {
var fileInput = document.getElementById("myFileInput");
var file = fileInput.files[0];
var reader = new FileReader();
reader.readAsText(file);
reader.addEventListener("load", function () {
var csvContent = reader.result;
console.log(csvContent, 'csvContent');
var records = csvContent.split("\n");
var result = [];
for (var i = 1; i < records.length; i++) {
var fields = records[i].split(",");
var record = {
time: fields[0],
station_name: fields[1],
meter_kwh: fields[2]
};
result.push(record);
}
console.log(result, 'result');
});
}
这种方式需要手动解析数据。因为 csvContent 是一个 string 类型。如下
js
time,station_name,meter_kwh
2021/10/1 0:00,一号电站,54.91870189
2021/10/1 0:00,二号电站,73.62640804
2021/10/1 0:00,三号电站,11.42062977
我们一般拿到这种数据,不管是填充到表格里面还是 Echarts,Antv 里都是需要转换一下的。因此在这里手动转换。转换的时候需要知道 key 的值,这里是写死的。所以有一定缺点。 这种方式是用户通过 Input 框来上传一个文件,然后前端进行解析。
方法2:Input + Papaparse 解析 csv
Papaparse 是一个比较好用的解析 csv 的工具。并且提供了 Demo,非常方便。 从 Demo 可以看到,包含解析 csv 字符串,解析通过 Input 输入框上传的文件,解析远程 URL资源形式的 csv 文件,将 json 解析成 csv。
注:papaparse 解析本地文件, 需要的文件格式是从 DOM 中获得的 File 对象, 不能直接使用 require() 导入文件。所以需要借助 Input。
通过 Papaparse 就可以将方法1中的代码进行优化,直接使用框架而不是手动解析。代码如下:
js
import Papa from 'papaparse';
const read2 = () => {
var fileInput = document.getElementById("myFileInput");
var file = fileInput.files[0];
Papa.parse(file, {
// header: true,
delimiter: ',', // 字段分隔符
complete: (results) => {
console.log(results, 'results')
const csvData = results.data
}
});
;
}
这里的 Result 结构是下面这样的:
js
results = {
data: [
['time', 'station_name', 'meter_kwh'],
['2021/10/1 0:00', '一号电站', '54.91870189'],
['2021/10/1 0:00', '二号电站', '73.62640804'],
['2021/10/1 0:00', '三号电站', '11.42062977']
], // parsed data
errors: [], // errors encountered
meta: {
delimiter: ',',
linebreak: '\r\n',
aborted: false,
truncated: false,
cursor: 2372
} // extra parse info
}
如果想要转换成我们想要的通用的数据结构的话,Papaparse 提供了一个很方便的属性,就是 header: true。在 Papa.parse 的第二个参数里面加上即可。转换之后如下,从 data 拿数据即可。
js
results = {
data: [
{time: '2021/10/1 0:00', station_name: '一号电站', meter_kwh: '54.91870189'},
{time: '2021/10/1 0:00', station_name: '二号电站', meter_kwh: '73.62640804'},
{time: '2021/10/1 0:00', station_name: '三号电站', meter_kwh: '11.42062977'}
], // parsed data
errors: [], // errors encountered
meta: {
delimiter: ',',
linebreak: '\r\n',
aborted: false,
truncated: false,
cursor: 2372
} // extra parse info
}
方法3:XMLHttpRequest + Papaparse
这种方法是不使用 Input 来获取文件,直接从文件目录里面读取文件,需要使用 ajax 请求这个文件。
js
import Papa from 'papaparse';
const readCSVFile = (filePath) => {
if(!filePath) throw new Error('请输入正确的文件路径')
const xhr = new window.XMLHttpRequest()
xhr.open('GET', filePath, false)
xhr.overrideMimeType('text/html;charset=GB2312')
xhr.send(null)
const { data } = Papa.parse(xhr.responseText, {
header: true
})
return { data }
}
const { data } = readCSVFile('/csv/meters-mini.csv')
console.log(data, 'data-readCSVFile')
readCSVFile 的参数是 path。如果是Vue项目, 资源需要放在public文件夹下。
xhr.responseText 是字符串类型,通过 papaparse 解析,这样就可以拿到我们想要的数据结构。
方法4:使用 @rollup/plugin-dsv 插件
这个插件是基于 d3 的一个数据处理工具。github.com/d3/d3-dsv 因为图表很多涉及 csv 转换成对象的那种 Item 结构。所以 d3 直接做了一个工具。方便数据转换。
插件具体使用方法见:How do I import csv file?
链接里面也有在线 Demo,写的很清楚,这里不过多赘述。
Antv 相关
在使用比如 Antv 图表库的时候,Antv 本身提供了 csv 类型文件的解析。就不需要我们自己去解析了。比如 在 G2 的 V3 版本中使用 Connector 可以很方便的解析。
然后我去看最新的 Antv V5 版本的文档,没看到相关 Connector 里支持 csv 的说明。但通过看 G2 源码可以看到,它还是支持 csv 的。本质上还是使用的 d3-dsv 这个工具...
Antv 源码里用的挺多 d3 的插件的,好吧。这个参考很厉害...
思考
其实总结了这么多方法。实际用的时候可能没必要这么麻烦。
业务场景通常情况下的 csv 是动态数据。最好是后端来通过一个接口将 csv 返回。说到通过接口返回 csv 了,那直接一步到位返回 json 就好了,没必要在前端去处理成 json。 后端来转换的话,易于理解,方便维护 Debug。
总结这些前端处理 csv 的情况主要是为了有时候后端我们不可控,或者某些场景只有静态 csv 的时候,才去这样做。最好的方案一定不是传输 csv。
参考
JS读取本地CSV文件数据 blog.csdn.net/weixin_4397...
vue3.0中的vite如何引入markdown文件为页面 www.cnblogs.com/tyusBlog/p/...
JS读取与解析本地文本类文件 juejin.cn/post/722580...
另外,这里有一篇 How to Import a CSV Using Next.js and Node.js,其实就是:方法2:Input + Papaparse 解析 csv。