前端解析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。

相关推荐
像风一样自由20201 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem2 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊2 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术2 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
GISer_Jing2 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止3 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall3 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴3 小时前
简单入门Python装饰器
前端·python
袁煦丞3 小时前
数据库设计神器DrawDB:cpolar内网穿透实验室第595个成功挑战
前端·程序员·远程工作
天天扭码4 小时前
从图片到语音:我是如何用两大模型API打造沉浸式英语学习工具的
前端·人工智能·github