csv表格处理(下)--纯JS解析导入csv
多日前的上篇介绍了csv表格,以及JS结合后端PHP解析表格填充表单的方法。其中csv转换成二维数组的时候逻辑比较复杂多坑,幸好PHP有丰富的库函数来处理,而现在用JS解析的话就没有那么幸运了,一切都要自己撸一个出来 或者 →_→ 引入一个库。
JS导入CSV--读取文本
JS能前端读取文件吗?以前只有通过 IE的ActiveXObject或者Flash才能本地读取文件。随着H5的出现,这个问题有普遍解了。Talk is cheap,show you the code
$.fn.csv2arr = function( ){
var files = $(this)[0].files;
if( typeof(FileReader) !== 'undefined' ){ //H5
var reader = new FileReader();
reader.readAsText( files[0] ); //以文本格式读取
reader.onload = function(evt){
var data = evt.target.result; //读到的数据
console.log(data);
}
}else{
alert("IE9及以下浏览器不支持,请使用Chrome或Firefox浏览器");
}
}
//调用方法
$("#startBtn").click(function(){
$("#csvInput").csv2arr();
});
这里的关键就是 FileReader,是H5标准里的读取文件的一个标准实现方式,IE10及以上版本以及chrome/firefox/safari等支持。调用方式方法也比较简单,只需要传入文件输入框的DOM,设定读取方式然后绑定回调函数就行了。这里使用的是 readAsText() 的方式,读取为文本格式。参考火狐的MDN文档,还有以base64,二进制等方式,可自行参考尝试。UTF8文本文件读取如下:
注意:readAsText()会自动把utf8文件的BOM头(如果有的话)去除,其它读取方式要注意手动去除。

题外话:为什么H5会出现这种直接读取本地文件的API,对安全的威胁大吗?其实这对浏览器用户的安全威胁是基本上没有扩大的,试想一下,原来没有这种读本地文件的API的时候,网站有没有获取本地文件的权限?当然是有的,还是通过这个input type="file",绑定一个onchange事件到 Ajax提交,用户的文件就悄悄地传到网站后端去了。这问题还是得靠提高网民的安全意识,像以前的钓鱼盗号网站,伪造个QQ登录界面就能坐收渔利。这种也能伪造一个下载按钮和对话框,诱导用户把重要机密文件上传上去。
JS导入CSV--文本解析插件
因为JS没有像PHP那样的CSV处理函数,上一篇文章说到里面有不少复杂情况要处理,那么最机(鸡)智(贼)的方法当然是:找插件。其中用的人最多的csv插件是PapaParse.js。经典的使用方法如下
// Parse local CSV file
$("#csvBtn").click(function(){ var file = $("input[name=csv]").[0].files[0];
Papa.parse(file, {
complete: function(results) {
console.log("Finished:", results.data);
}
}); });
这个插件比较强大,解析上基本没有什么大问题,但仍然不是十分完善。问题如下:
- 文件最末尾的空行没有自动去除,可能会导致表单填多一点空数据;
- 不能自动识别UTF8与GBK,中文解析可能乱码;
- UTF8编码下, \r\n与\n混用时有可能会解析出问题,这个是PapaParse解析的算法问题,还请高手去其官方github提供修复。
JS导入CSV--编码自动识别
刚说到的第三点,如果表格内容有中文的话,就是个大问题了。因为一般网页的编码是UTF8,导出的表格也会是UTF8编码格式,如果不修改直接上传则为UTF8。但是如果修改,Windows平台下的常用表格软件包括Office和WPS全都将其转换成GBK编码。如果程序没有自动识别编码处理,将有很大概率导致乱码。
另一方面,如果网页使用GBK编码格式下载,也不能确保用户上传的文件就一定是GBK,因为MAC系统用的是UTF8,可能本来GBK的在修改后就成了UTF8了。
或者可以给个下拉栏让用户手动选择编码格式,但是你要指导用户知道编码格式是什么东西,怎么查看,这可不是什么容易让人接受的事。那怎么做编码自动识别呢?UTF8与GBK是不是有明显的编码特征用以区分,报歉的是还真没有。那怎么办?找轮子。在哪找?对于JS的轮子,国内有个很好的CDN库,虽然介绍是全英的但还是很好找。我们要找的是编码解码,那就Ctrl+F搜 encod (encode和encoding的前面几个单词),一个个看看介绍,还真能找到一个,名为jschardet。

点进去,没有详细说明,那就再去其github页。看看示例代码
// "àíàçã" in UTF-8
jschardet.detect("\xc3\xa0\xc3\xad\xc3\xa0\xc3\xa7\xc3\xa3")
// { encoding: "UTF-8", confidence: 0.9690625 } // "次常用國字標準字體表" in Big5
jschardet.detect("\xa6\xb8\xb1\x60\xa5\xce\xb0\xea\xa6\x72\xbc\xd0\xb7\xc7\xa6\x72\xc5\xe9\xaa\xed")
// { encoding: "Big5", confidence: 0.99 }
什么鬼?看起来用的好像不是普通字符串啊,看起来像是十六进制码的样子。实践了发现,传普通字符串进去全部都是识别为ASCII编码,确实有点难搞啊。怎么办呢?
莫慌莫慌,我们不是要读取本地文件拿来解析吗?再看看火狐的MDN文档除了readAsText()读取为字符串以外还有什么方法可以用。有个readAsBinaryString(),但是并不是标准的H5读取方法,有些浏览器可能不支持。再看有一个readAsDataURL(),这什么东西呢,试试便知道。结果得到一串这样的东西
data:text/csv;base64,NiywzczYwPvM2KGksLIKMyzN0LDdtvLLuaGkx+0KOCy2xc3+oaS3xrDCxMkK
改文件再试多几次,原来是这样子的:前面的 data:text/csv;base64, 是固定字符串,仅对火狐,chrome和IE前面的是 data:;base64, ,后面的那一串是文件内容经过base64编码而成。那么把后面这个一串解码出来看看,IE>=10、火狐、chrome有原生的base64解码函数 atob()。然后就得到了一个英文正常,中文全是乱码的字符串了,而且这个字符串的乱码看起来不像UTF8也不像GBK。那么很可能这就是十六进制码了吧,用jschardet检测一下,成功了!

总结整理
到这里,我们已经用第三方的JS解决了最大的两个难题,编码识别和CSV解析。那么就把这些整合一下,封装成一个更方便调用的方法吧
/**
* csv file to 2D arr
* */
$.fn.csv2arr = function( callback ){
if( typeof(FileReader) == 'undefined' ){ //if not H5
alert("IE9及以下浏览器不支持,请使用Chrome或Firefox浏览器\nYour browser is too old,please use Chrome or Firefox");
return false;
}
if( ! $(this)[0].files[0]){
alert("请选择文件\nPlease select a file");
return false;
}
var fReader = new FileReader();
fReader.readAsDataURL( $(this)[0].files[0] );
$fileDOM = $(this);
fReader.onload = function(evt){
var data = evt.target.result;
// console.log( data );
var encoding = checkEncoding( data );
// console.log(encoding);
//转换成二维数组,需要引入Papaparse.js
Papa.parse( $($fileDOM)[0].files[0], {
encoding: encoding,
complete: function(results) { // UTF8 \r\n与\n混用时有可能会出问题
// console.log(results);
var res = results.data;
if( res[ res.length-1 ] == ""){ //去除最后的空行
res.pop();
}
callback && callback( res );
}
});
}
fReader.onerror = function(evt){
// console.log(evt);
alert("文件已修改,请重新选择(Firefox)\nThe file has changed,please select again.(Firefox)");
} //检查编码,引用了 jschardet
function checkEncoding( base64Str ){
//这种方式得到的是一种二进制串
var str = atob( base64Str.split(";base64,")[1] );
// console.log(str);
//要用二进制格式
var encoding = jschardet.detect( str );
encoding = encoding.encoding;
// console.log( encoding );
if( encoding == "windows-1252"){ //有时会识别错误(如UTF8的中文二字)
encoding = "ANSI";
}
return encoding;
}
}
使用例子
<input type="file" name="csvfile" />
<input type="button" onclick="csv2()" value="JS转换"/> <script src="__PJS__/jquery.js"></script>
<script src="__PJS__/papaparse.js"></script>
<script src="__PJS__/jschardet.js"></script>
<script>
function csv2(){
$("input[name=csvfile]").csv2arr(function(res){
alertTips("F12打开浏览器控制台看看");
console.log( res );
});
}
</script>
下载与更新
演示地址DEMO
zip打包下载
Github地址,求加星,求一起修BUG
DRY--Don't Repeat Yourself. 别乱造些满是bug的轮子
csv表格处理(下)--纯JS解析导入csv的更多相关文章
- ios webview下纯JS实现长按
app,其中有长按LI列表弹出菜单,只要清楚五个方法就行:ontouchstart.ontouchmove.ontouchend.setTimeout.clearTimeout 1.首先在我们按下手指 ...
- mysql SQLyog导入csv数据失败怎么办?
分享下mysql使用SQLyog导入csv数据失败的解决方法 给mysql导入数据,选中某个表选择导入--导入使用本地csv数据即可,单有的时候不知道什么问题导入不成功!!! 给mysql导入数据,使 ...
- csv表格处理(上)-- JS 与 PHP 协作导入导出
CSV简介 在开发后台管理系统的时候,几乎无可避免的会遇到需要导入导出Excel表格的需求.csv也是表格的一种,其中文名为“逗号分隔符文件”.在Excel中打开如下图左边所示,在记事本打开如下图右边 ...
- 【 D3.js 进阶系列 — 1.0 】 CSV 表格文件的读取
在入门系列的教程中.我们经常使用 d3.json() 函数来读取 json 格式的文件.json 格式非常强大.但对于普通用户可能不太适合,普通用户更喜欢的是用 Microsoft Excel 或 O ...
- nodejs:导出Excel和解析导入的Excel
用的是koa2框架,但好好处理一下,用express框架也是可以的.导出的Excel是xlsx的格式,解析导入Excel的有xlsx和csv格式.通常导入Excel是要上传的,然后获取文件的路径,这里 ...
- CSS控制XML与通过js解析xml然后通过html显示xml中的数据
使用CSS控制XML的显示 book.css bookname{ display:block;color:Red} author{ display:block;font-style:italic} p ...
- 《项目经验》--后台一般处理程序向前台JS文件传递JSON,JS解析JSON,将数据显示在界面--显示在DropDownList 或 显示在动态创建的table中
http://blog.csdn.net/mazhaojuan/article/details/8599167 先看一下我要实现的功能界面: 这篇文章主要介绍:后台一般处理程序把从数据库查找的数据,转 ...
- PHP处理CSV表格文件的常用操作方法是怎么样呢
php来说,fgetcsv读入csv表格,返回一个数组,然后foreach输出成HTML的<table>,这步操作几行代码就能实现,非常简单.工作量主要还在于浏览器前端,建议你用jQuer ...
- 纯js实现分页
原理:所有数据已加载好,js通过遍历部分显示,实现分页效果 html代码 <html> <head> <meta charset='utf-8'> <scri ...
随机推荐
- 代码的坏味道(9)——异曲同工的类(Alternative Classes with Different Interfaces)
坏味道--异曲同工的类(Alternative Classes with Different Interfaces) 特征 两个类中有着不同的函数,却在做着同一件事. 问题原因 这种情况往往是因为:创 ...
- OA办公自动化系统源码
最新extjs6富客户端,.net平台开发,sql server数据库,基础权限人员基础平台,可方便二次开发,使用EF为orm,autofac为ioc,Castle为基础的aop,实现常用OA系统功能 ...
- C语言中的结构体
用户自己建立自己的结构体类型 1. 定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...
- 你搞懂 ORACLE、 SQLSERVER、MYSQL与DB2的区别了吗
ORACLE. SQLSERVER.MYSQL与DB2的区别--平台性: Oracle.MYSQL与DB2可在所有主流平台上运行: SQL Server只能在Windows下运行: --安 ...
- Maven+Spring+Spring MVC+MyBatis+MySQL,搭建SSM框架环境【转】
项目建设完成之后的结构: 数据库的表结构如下: 环境建设:搭建Maven环境.Tomcat环境.需要MySql 数据库支持,使用的编程工具Eclipse (这些是前期准备): 开始创建工程: 1.创建 ...
- Atitit 游戏的原理与概论attilax总结
Atitit 游戏的原理与概论attilax总结 1. 游戏历史2 1.1.1. 盘点PC游戏史上最重要的50款游戏2 1.1.2. 回味人类文明进程 五款经典的历史游戏2 2. 游戏类型(主要分为6 ...
- 【干货分享】前端面试知识点锦集02(CSS篇)——附答案
二.CSS部分 1.解释一下CSS的盒子模型? 回答一:a.标准的css盒子模型:宽度=内容的宽度+边框的宽度+加上内边具的宽度b.网页设计中常听的属性名:内容(content).填充(padding ...
- 浅析天猫H5站点
前言 我们做前端开发的时候,很有可能会做一个竞品分析,比如我就做过去哪儿.艺龙.同程等与携程的移动站点竞品分析,竞品分析的目的一般是技术对比,但是更多的是业务对比,知己知彼,百战不殆:我们同时会借鉴. ...
- 改变你代码习惯的ES6
最近读阮一峰老师的ES6标准入门,让我感觉到了ES6的强大之处,读书之余整理了一些笔记,因为边读边记录的,所以可能会比较杂乱. ECMAScript和Javascript的关系 1996年11月,Ja ...
- ES6笔记(一):ES6所改良的javascript“缺陷”
块级作用域 ES5没有块级作用域,只有全局作用域和函数作用域,由于这一点,变量的作用域甚广,所以一进入函数就要马上将它创建出来.这就造成了所谓的变量提升. ES5的"变量提升"这一 ...