前端解析CSV实践总结

由于网络的资源比较杂乱,自己看了并实践之后,总结一下

方法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。

相关推荐
柳杉4 分钟前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog16 分钟前
低端设备加载webp ANR
前端·算法
LKAI.37 分钟前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi
刺客-Andy1 小时前
React 第七十节 Router中matchRoutes的使用详解及注意事项
前端·javascript·react.js
前端工作日常1 小时前
我对eslint的进一步学习
前端·eslint
禁止摆烂_才浅2 小时前
VsCode 概览尺、装订线、代码块高亮设置
前端·visual studio code
程序员猫哥2 小时前
vue跳转页面的几种方法(推荐)
前端
代码老y3 小时前
十年回望:Vue 与 React 的设计哲学、演进轨迹与生态博弈
前端·vue.js·react.js
一条上岸小咸鱼3 小时前
Kotlin 基本数据类型(五):Array
android·前端·kotlin
大明883 小时前
用 mouseover/mouseout 事件代理模拟 mouseenter/mouseleave
前端·javascript