我的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>

我用这个文件进行了测试

其他回答

根据公认的答案,

我把这里的1改成了0

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

更改为

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

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

你可以使用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; }
        });
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引擎上的第一个替代方案之前执行,并考虑将引号作为未加引号的值的一部分。我不会问的,我刚弄好了。

这是一个老问题,在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文件中可能出现的所有“特殊情况”(如转义引号)之前,我制定了这个解决方案。我把我的答案留给那些想要快速和肮脏的东西的人,但为了准确起见,我推荐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/