我的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>
注意:在我被提醒有效CSV文件中可能出现的所有“特殊情况”(如转义引号)之前,我制定了这个解决方案。我把我的答案留给那些想要快速和肮脏的东西的人,但为了准确起见,我推荐Evan的答案。
当你的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/
不需要自己写……
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有点可怕,因为没有真正的官方标准,而且许多带分隔符的文本编写者不考虑边界情况。
这个问题很老了,但我相信现在有了更好的解决方案Papa Parse。它是我在贡献者的帮助下编写的一个库,用于解析CSV文本或文件。它是我所知道的唯一支持千兆字节大小文件的JS库。它还能优雅地处理畸形输入。
1分钟解析1gb文件
(更新:使用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引擎上的第一个替代方案之前执行,并考虑将引号作为未加引号的值的一部分。我不会问的,我刚弄好了。
你可以使用PapaParse来帮助你。
https://www.papaparse.com/
这是一个代码依赖。
https://codepen.io/sandro-wiggers/pen/VxrxNJ
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; }
});
有点晚了,但我希望这能帮助到一些人。
前段时间,我甚至遇到了一个问题,其中字符串数据包含\n在读取文件时,它用于读取不同的行。
Eg.
"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
});
}
}
使用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是数据操作的最佳替代品之一。它是开源的,可以免费使用,但它也是模块化的,所以我们可以只导入fetch模块。
这里有一个基本的例子。我们将使用遗留模式,所以我将导入整个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>
If we don't want to use any library and we just want to use pain JavaScrip (Vanilla JS) and we managed to get the text content of a file as data and we don't want to use d3 we can implement a simple function that will split the data into a text array then we will extract the first line and split into a headers array and the rest of the text will be the lines we will process. After, we map each line and extract its values and create a row object from an array created from mapping each header to its correspondent value from values[index].
注意:
We also we going to use a little trick array objects in JavaScript can also have attributes. Yes so we will define an attribute rows.headers and assign the headers to it.
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>
我用这个文件进行了测试