如何使用JavaScript从*.CSV文件读取数据?

我的CSV数据是这样的:

heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2
...

如何使用JavaScript读取数据并将其转换为这样的数组?:

[
heading1: value1_1,
heading2: value2_1,
heading3: value3_1,
heading4: value4_1
heading5: value5_1
],[
heading1: value1_2,
heading2: value2_2,
heading3: value3_2,
heading4: value4_2,
heading5: value5_2
]
....

我试过这个代码,但运气不好!:

<script type="text/javascript">
var allText =[];
var allTextLines = [];
var Lines = [];


var txtFile = new XMLHttpRequest();
txtFile.open("GET", "file://d:/data.txt", true);
txtFile.onreadystatechange = function()
{
allText = txtFile.responseText;
allTextLines = allText.split(/\r\n|\n/);
};


document.write(allTextLines);
document.write(allText);
document.write(txtFile);
</script>
934264 次浏览

注意:我炮制了这个解决方案之前,我被提醒所有的“特殊情况”,可以发生在一个有效的CSV文件,如转义引号。我把我的答案留给那些想要快速和肮脏的东西的人,但为了准确起见,我推荐埃文的回答


当你的data.txt文件是一个逗号分隔的长字符串,没有换行符时,这段代码将工作:

data.txt:

 heading1,heading2,heading3,heading4,heading5,value1_1,...,value5_2

javascript:

$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {processData(data);}
});
});


function processData(allText) {
var record_num = 5;  // or however many elements there are in each row
var allTextLines = allText.split(/\r\n|\n/);
var entries = allTextLines[0].split(',');
var lines = [];


var headings = entries.splice(0,record_num);
while (entries.length>0) {
var tarr = [];
for (var j=0; j<record_num; j++) {
tarr.push(headings[j]+":"+entries.shift());
}
lines.push(tarr);
}
// alert(lines);
}

下面的代码将工作在一个“真正的”CSV文件,每组记录之间的换行:

data.txt:

heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2

javascript:

$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {processData(data);}
});
});


function processData(allText) {
var allTextLines = allText.split(/\r\n|\n/);
var headers = allTextLines[0].split(',');
var lines = [];


for (var i=1; i<allTextLines.length; i++) {
var data = allTextLines[i].split(',');
if (data.length == headers.length) {


var tarr = [];
for (var j=0; j<headers.length; j++) {
tarr.push(headers[j]+":"+data[j]);
}
lines.push(tarr);
}
}
// alert(lines);
}

http://jsfiddle.net/mblase75/dcqxr/

根据接受的答案

我把这里的1改成了0

for (var i=1; i<allTextLines.length; i++) {

更改为

for (var i=0; i<allTextLines.length; i++) {

它将计算一个文件与一个连续的行作为一个allTextLines。长度为1。因此,如果循环从1开始,只要它小于1,它就永远不会运行。因此出现了空白警报框。

不需要自己写……

jQuery-CSV库有一个名为$.csv.toObjects(csv)的函数,它自动进行映射。

注意:该库旨在处理RFC 4180兼容的任何CSV数据,包括大多数“简单”解决方案忽略的所有糟糕的边缘情况。

就像@Blazemonger已经说过的,首先您需要添加换行符以使数据有效的CSV。

使用以下数据集:

heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2

使用代码:

var data = $.csv.toObjects(csv):

保存在'data'中的输出将是:

[
{ heading1:"value1_1",heading2:"value2_1",heading3:"value3_1",heading4:"value4_1",heading5:"value5_1" }
{ heading1:"value1_2",heading2:"value2_2",heading3:"value3_2",heading4:"value4_2",heading5:"value5_2" }
]

注意:从技术上讲,您编写键值映射的方式是无效的JavaScript。包含键-值对的对象应该用括号括起来。

如果你想自己尝试一下,我建议你看看'toObjects()'标签下的基本使用演示

免责声明:我是jQuery-CSV的原始作者。

更新:

编辑以使用op提供的数据集,并包括一个到演示的链接,其中可以测试数据的有效性。

更新2:

由于关闭谷歌代码。jquery-csv已经迁移到GitHub

不要用逗号分隔——这对大多数CSV文件都不起作用,而且这个问题的视图太多了,提问者的输入数据不可能适用于所有人。解析CSV有点可怕,因为没有真正的官方标准,而且许多带分隔符的文本编写者不考虑边界情况。

这个问题很老了,但我相信现在有一个更好的解决方案,爸爸解析是可用的。它是我在贡献者的帮助下编写的一个库,用于解析CSV文本或文件。它是我所知道的唯一支持千兆字节大小文件的JS库。它还能优雅地处理畸形输入。

1分钟解析1gb文件: Parsed 1gb file in 1 minute

.

在Papa Parse 4中,同样的文件在Firefox中只花了大约30秒。Papa Parse 4现在是浏览器的已知最快的CSV解析器。)

解析文本非常简单:

var data = Papa.parse(csvString);

解析文件也很简单:

Papa.parse(file, {
complete: function(results) {
console.log(results);
}
});

流文件是类似的(这里是一个流远程文件的例子):

Papa.parse("http://example.com/bigfoo.csv", {
download: true,
step: function(row) {
console.log("Row:", row.data);
},
complete: function() {
console.log("All done!");
}
});

如果你的网页在解析过程中锁定,Papa可以使用网络工作者来保持你的网站反应性。

如果存在标题行,Papa可以自动检测分隔符并将值与标题列匹配。它还可以将数值转换为实际的数字类型。它可以适当地解析换行符、引号和其他奇怪的情况,甚至可以尽可能健壮地处理畸形输入。我从现有的库中汲取灵感来制作Papa,所以支持其他JS实现。

下面是一个JavaScript函数,用于解析CSV数据,计算引号内的逗号。

// Parse a CSV row, accounting for commas inside quotes
function parse(row){
var insideQuote = false,
entries = [],
entry = [];
row.split('').forEach(function (character) {
if(character === '"') {
insideQuote = !insideQuote;
} else {
if(character == "," && !insideQuote) {
entries.push(entry.join(''));
entry = [];
} else {
entry.push(character);
}
}
});
entries.push(entry.join(''));
return entries;
}

函数解析CSV文件的示例如下:

"foo, the column",bar
2,3
"4, the value",5

数组:

// csv could contain the content read from a csv file
var csv = '"foo, the column",bar\n2,3\n"4, the value",5',


// Split the input into lines
lines = csv.split('\n'),


// Extract column names from the first line
columnNamesLine = lines[0],
columnNames = parse(columnNamesLine),


// Extract data from subsequent lines
dataLines = lines.slice(1),
data = dataLines.map(parse);


// Prints ["foo, the column","bar"]
console.log(JSON.stringify(columnNames));


// Prints [["2","3"],["4, the value","5"]]
console.log(JSON.stringify(data));

以下是如何将数据转换为对象,如D3的csv解析器(这是一个可靠的第三方解决方案):

var dataObjects = data.map(function (arr) {
var dataObject = {};
columnNames.forEach(function(columnName, i){
dataObject[columnName] = arr[i];
});
return dataObject;
});


// Prints [{"foo":"2","bar":"3"},{"foo":"4","bar":"5"}]
console.log(JSON.stringify(dataObjects));

这是一个此代码的工作提琴

享受吧!——

下面是读取外部CSV到Javascript的另一种方法(使用jQuery)。

它有点冗长,但我觉得通过将数据读入数组,您可以准确地遵循这个过程,并使故障排除变得容易。

也许能帮到别人。

数据文件示例:

Time,data1,data2,data2
08/11/2015 07:30:16,602,0.009,321

下面是代码:

$(document).ready(function() {
// AJAX in the data file
$.ajax({
type: "GET",
url: "data.csv",
dataType: "text",
success: function(data) {processData(data);}
});


// Let's process the data from the data file
function processData(data) {
var lines = data.split(/\r\n|\n/);


//Set up the data arrays
var time = [];
var data1 = [];
var data2 = [];
var data3 = [];


var headings = lines[0].split(','); // Splice up the first row to get the headings


for (var j=1; j<lines.length; j++) {
var values = lines[j].split(','); // Split up the comma seperated values
// We read the key,1st, 2nd and 3rd rows
time.push(values[0]); // Read in as string
// Recommended to read in as float, since we'll be doing some operations on this later.
data1.push(parseFloat(values[1]));
data2.push(parseFloat(values[2]));
data3.push(parseFloat(values[3]));


}


// For display
var x= 0;
console.log(headings[0]+" : "+time[x]+headings[1]+" : "+data1[x]+headings[2]+" : "+data2[x]+headings[4]+" : "+data2[x]);
}
})

希望这对将来的人有所帮助!

function CSVParse(csvFile)
{
this.rows = [];


var fieldRegEx = new RegExp('(?:\s*"((?:""|[^"])*)"\s*|\s*((?:""|[^",\r\n])*(?:""|[^"\s,\r\n]))?\s*)(,|[\r\n]+|$)', "g");
var row = [];
var currMatch = null;


while (currMatch = fieldRegEx.exec(this.csvFile))
{
row.push([currMatch[1], currMatch[2]].join('')); // concatenate with potential nulls


if (currMatch[3] != ',')
{
this.rows.push(row);
row = [];
}


if (currMatch[3].length == 0)
break;
}
}

我喜欢尽可能多地使用正则表达式。此正则表达式将所有项视为带引号或不带引号,后跟列分隔符或行分隔符。或者文本的结尾。

这就是为什么最后一个条件——没有它,它将是一个无限循环,因为模式可以匹配零长度字段(在csv中完全有效)。但由于$是一个零长度断言,它不会进展到不匹配并结束循环。

仅供参考,我必须使第二种选择排除引号周围的值;似乎它在我的javascript引擎上的第一个替代方案之前执行,并考虑将引号作为未加引号的值的一部分。我不会问的,我刚弄好了。

我使用d3.js解析csv文件。非常容易使用。 这里是文档.

. 0

步骤:

  • NPM安装d3-request

使用Es6;

import { csv } from 'd3-request';
import url from 'path/to/data.csv';


csv(url, function(err, data) {
console.log(data);
})

更多信息请参见文档

< >强更新- D3-request已弃用。你可以使用d3-fetch

您可以使用PapaParse帮助。 https://www.papaparse.com/ < / p >

这是一个代码依赖。 https://codepen.io/sandro-wiggers/pen/VxrxNJ < / p >

Papa.parse(e, {
header:true,
before: function(file, inputElem){ console.log('Attempting to Parse...')},
error: function(err, file, inputElem, reason){ console.log(err); },
complete: function(results, file){ $.PAYLOAD = results; }
});

如果你想在不使用Ajax的情况下解决这个问题,请使用FileReader() Web API

示例实现:

  1. 选择.csv文件
  2. 看到输出

function readSingleFile(e) {
var file = e.target.files[0];
if (!file) {
return;
}


var reader = new FileReader();
reader.onload = function(e) {
var contents = e.target.result;
displayContents(contents);
displayParsed(contents);
};
reader.readAsText(file);
}


function displayContents(contents) {
var element = document.getElementById('file-content');
element.textContent = contents;
}


function displayParsed(contents) {
const element = document.getElementById('file-parsed');
const json = contents.split(',');
element.textContent = JSON.stringify(json);
}


document.getElementById('file-input').addEventListener('change', readSingleFile, false);
<input type="file" id="file-input" />


<h3>Raw contents of the file:</h3>
<pre id="file-content">No data yet.</pre>


<h3>Parsed file contents:</h3>
<pre id="file-parsed">No data yet.</pre>

$(function() {


$("#upload").bind("click", function() {
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.csv|.xlsx)$/;
if (regex.test($("#fileUpload").val().toLowerCase())) {
if (typeof(FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function(e) {
var customers = new Array();
var rows = e.target.result.split("\r\n");
for (var i = 0; i < rows.length - 1; i++) {
var cells = rows[i].split(",");
if (cells[0] == "" || cells[0] == undefined) {
var s = customers[customers.length - 1];
s.Ord.push(cells[2]);
} else {
var dt = customers.find(x => x.Number === cells[0]);
if (dt == undefined) {
if (cells.length > 1) {
var customer = {};
customer.Number = cells[0];
customer.Name = cells[1];
customer.Ord = new Array();


customer.Ord.push(cells[2]);
customer.Point_ID = cells[3];
customer.Point_Name = cells[4];
customer.Point_Type = cells[5];
customer.Set_ORD = cells[6];
customers.push(customer);
}
} else {
var dtt = dt;
dtt.Ord.push(cells[2]);


}
}
}

实际上,你可以使用一个名为任何文本的轻量级库。

  • 安装依赖关系
npm i -D any-text
  • 使用自定义命令读取文件
var reader = require('any-text');
 

reader.getText(`path-to-file`).then(function (data) {
console.log(data);
});

或者使用async-await:

var reader = require('any-text');
 

const chai = require('chai');
const expect = chai.expect;
 

describe('file reader checks', () => {
it('check csv file content', async () => {
expect(
await reader.getText(`${process.cwd()}/test/files/dummy.csv`)
).to.contains('Lorem ipsum');
});
});

有点晚了,但我希望这能帮助到一些人。

前一段时间,即使我遇到了一个问题,字符串数据包含\n之间,而读取文件,它用来读取不同的行。

如。

"Harry\nPotter","21","Gryffindor"

在阅读:

Harry
Potter,21,Gryffindor

我在我的angular项目中使用了csvtojson库来解决这个问题。

您可以使用以下代码将CSV文件读取为字符串,然后将该字符串传递给csvtojson库,它将为您提供一个JSON列表。

示例代码:

const csv = require('csvtojson');
if (files && files.length > 0) {
const file: File = files.item(0);
const reader: FileReader = new FileReader();
reader.readAsText(file);
reader.onload = (e) => {
const csvs: string = reader.result as string;
csv({
output: "json",
noheader: false
}).fromString(csvs)
.preFileLine((fileLine, idx) => {
//Convert csv header row to lowercase before parse csv file to json
if (idx === 0) { return fileLine.toLowerCase() }
return fileLine;
})
.then((result) => {
// list of json in result
});
}
}

我使用jquery-csv来做到这一点。

evanplaice/jquery-csv

我提供两个例子如下

async function ReadFile(file) {
return await file.text()
}


function removeExtraSpace(stringData) {
stringData = stringData.replace(/,( *)/gm, ",")  // remove extra space
stringData = stringData.replace(/^ *| *$/gm, "") // remove space on the beginning and end.
return stringData
}


function simpleTest() {
let data = `Name, Age, msg
foo, 25, hello world
bar, 18, "!! 🐬 !!"
`
data = removeExtraSpace(data)
console.log(data)
const options = {
separator: ",", // default "," . (You may want to Tab "\t" or somethings.
delimiter: '"', // default "
headers: true // default true
}
// const myObj = $.csv.toObjects(data, options)
const myObj = $.csv.toObjects(data) // If you want to use default options, then you can omit them.
console.log(myObj)
}


window.onload = () => {
const inputFile = document.getElementById("uploadFile")
inputFile.onchange = () => {
const inputValue = inputFile.value
if (inputValue === "") {
return
}


const selectedFile = document.getElementById('uploadFile').files[0]
const promise = new Promise(resolve => {
const fileContent = ReadFile(selectedFile)
resolve(fileContent)
})


promise.then(fileContent => {
// Use promise to wait for the file reading to finish.
console.log(fileContent)
fileContent = removeExtraSpace(fileContent)
const myObj = $.csv.toObjects(fileContent)
console.log(myObj)
})
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/1.0.11/jquery.csv.min.js"></script>


<label for="uploadFile">Demo 1</label>
<input type="file" id="uploadFile" accept=".csv"/>
<button onclick="simpleTest()">Demo 2</button>

使用这个函数 csvToObjs你可以从CSV格式对象数组变换数据项。

function csvToObjs(string) {
const lines = data.split(/\r\n|\n/);
let [headings, ...entries] = lines;
headings = headings.split(',');
const objs = [];
entries.map(entry=>{
obj = entry.split(',');
objs.push(Object.fromEntries(headings.map((head, i)=>[head, obj[i]])));
})
return objs;
}




data = `heading1,heading2,heading3,heading4,heading5
value1_1,value2_1,value3_1,value4_1,value5_1
value1_2,value2_2,value3_2,value4_2,value5_2`
console.log(csvToObjs(data));

这是一个老问题,在2022年,有很多方法可以实现这一目标。首先,我认为D3是数据操作的最佳替代方案之一。它是开源的,可以免费使用,但它也是模块化的,所以我们可以只导入获取模块

这里有一个基本的例子。我们将使用遗留模式,因此我将导入整个D3库。现在,让我们调用d3.csv函数,它就完成了。这个函数在内部调用fetch方法,因此,它可以打开dataURL、url、files、blob等。

const fileInput = document.getElementById('csv')
const outElement = document.getElementById('out')
const previewCSVData = async dataurl => {
const d = await d3.csv(dataurl)
console.log({
d
})
outElement.textContent = d.columns
}


const readFile = e => {
const file = fileInput.files[0]
const reader = new FileReader()
reader.onload = () => {
const dataUrl = reader.result;
previewCSVData(dataUrl)
}
reader.readAsDataURL(file)
}


fileInput.onchange = readFile
<script type="text/javascript" src="https://unpkg.com/d3@7.6.1/dist/d3.min.js"></script>
<div>
<p>Select local CSV File:</p>
<input id="csv" type="file" accept=".csv">
</div>
<pre id="out"><p>File headers will appear here</p></pre>

如果我们不想使用任何库,只想使用painjavascrip (Vanilla JS),我们设法获得文件的文本内容为data,我们不想使用d3,我们可以实现一个简单的函数,将data分割为text数组,然后我们将提取第一行并分割为headers数组,而text的其余部分将是我们将处理的lines。之后,我们映射每个line并提取其values,并从将每个d30映射到d31中对应的值所创建的数组中创建row对象。

注意:

我们还将使用一个小技巧array对象在JavaScript中也可以有属性。是的,所以我们将定义一个属性rows.headers,并将headers赋值给它。

const data = `heading_1,heading_2,heading_3,heading_4,heading_5
value_1_1,value_2_1,value_3_1,value_4_1,value_5_1
value_1_2,value_2_2,value_3_2,value_4_2,value_5_2
value_1_3,value_2_3,value_3_3,value_4_3,value_5_3`


const csvParser = data => {
const text = data.split(/\r\n|\n/)
const [first, ...lines] = text
const headers = first.split(',')
const rows = []
rows.headers = headers
lines.map(line => {
const values = line.split(',')
const row = Object.fromEntries(headers.map((header, i) => [header, values[i]]))
rows.push(row)
})


return rows
}


const d = csvParser(data)
// Accessing to the theaders attribute
const headers = d.headers
console.log({headers})
console.log({d})

最后,让我们使用获取和解析csv文件来实现一个普通的JS文件加载器。

const fetchFile = async dataURL => {
return await fetch(dataURL).then(response => response.text())
}


const csvParser = data => {
const text = data.split(/\r\n|\n/)
const [first, ...lines] = text
const headers = first.split(',')
const rows = []
rows.headers = headers
lines.map(line => {
const values = line.split(',')
const row = Object.fromEntries(headers.map((header, i) => [header, values[i]]))
rows.push(row)
})


return rows
}


const fileInput = document.getElementById('csv')
const outElement = document.getElementById('out')
const previewCSVData = async dataURL => {
const data = await fetchFile(dataURL)
const d = csvParser(data)
console.log({ d })
outElement.textContent = d.headers
}


const readFile = e => {
const file = fileInput.files[0]
const reader = new FileReader()
reader.onload = () => {
const dataURL = reader.result;
previewCSVData(dataURL)
}
reader.readAsDataURL(file)
}


fileInput.onchange = readFile
<script type="text/javascript"  src="https://unpkg.com/d3@7.6.1/dist/d3.min.js"></script>
<div>
<p>Select local CSV File:</p>
<input id="csv" type="file" accept=".csv">
</div>
<pre id="out"><p>File contents will appear here</p></pre>

我使用这个文件来测试它