我的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>
这是一个老问题,在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>
我用这个文件进行了测试
不要用逗号分隔——这对大多数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实现。
不需要自己写……
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
下面是一个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));
这是这段代码的工作原理。
享受吧!——伦