Javascript 如何使用javascript从*.CSV文件中读取数据?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7431268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:14:10  来源:igfitidea点击:

How to read data From *.CSV file using javascript?

javascriptjquery

提问by Mahesh Thumar

My csv data looks like this:

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

标题1,标题2,标题3,标题4,标题5,值1_1,值2_1,值3_1,值4_1,值5_1,值1_2,值2_2,值3_2,值4_2,值5_2....

How do you read this data and convert to an array like this using Javascript?:

您如何使用 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 ]....

[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]...

I've tried this code but no luck!:

我试过这段代码,但没有运气!:

<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);<br>
    document.write(allText);<br>
    document.write(txtFile);<br>
</script>

采纳答案by Blazemonger

NOTE:I concocted this solution before I was reminded about all the "special cases" that can occur in a valid CSV file, like escaped quotes. I'm leaving my answer for those who want something quick and dirty, but I recommend Evan's answerfor accuracy.

注意:在我被提醒可能出现在有效 CSV 文件中的所有“特殊情况”之前,我炮制了这个解决方案,例如转义引号。我将我的答案留给那些想要快速而肮脏的人,但为了准确起见,我建议Evan 的答案



This code will work when your data.txtfile is one long string of comma-separated entries, with no newlines:

当您的data.txt文件是一长串以逗号分隔的条目且没有换行符时,此代码将起作用:

data.txt:

数据.txt:

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

javascript:

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);
}

The following code will work on a "true" CSV file with linebreaks between each set of records:

以下代码将处理“真实”CSV 文件,每组记录之间带有换行符:

data.txt:

数据.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:

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/

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

回答by Evan Plaice

No need to write your own...

不需要自己写...

The jQuery-CSVlibrary has a function called $.csv.toObjects(csv)that does the mapping automatically.

jQuery的CSV库有一个调用的函数$.csv.toObjects(csv)是自动完成的映射。

Note: The library is designed to handle any CSV data that is RFC 4180compliant, including all of the nasty edge cases that most 'simple' solutions overlook.

注意:该库旨在处理符合RFC 4180 的任何 CSV 数据,包括大多数“简单”解决方案忽略的所有令人讨厌的边缘情况。

Like @Blazemonger already stated, first you need to add line breaks to make the data valid CSV.

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

Using the following dataset:

使用以下数据集:

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

Use the code:

使用代码:

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

The output saved in 'data' will be:

保存在“数据”中的输出将是:

[
  { 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" }
]

Note: Technically, the way you wrote the key-value mapping is invalid JavaScript. The objects containing the key-value pairs should be wrapped in brackets.

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

If you want to try it out for yourself, I suggest you take a look at the Basic Usage Demonstrationunder the 'toObjects()' tab.

如果您想亲自尝试一下,我建议您查看“toObjects()”选项卡下的基本用法演示

Disclaimer: I'm the original author of jQuery-CSV.

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

Update:

更新:

Edited to use the dataset that the op provided and included a link to the demo where the data can be tested for validity.

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

Update2:

更新2:

Due to the shuttering of Google Code. jquery-csv has moved to GitHub

由于谷歌代码的关闭。jquery-csv 已移至 GitHub

回答by Matt

Don't split on commas -- it won't work for most CSV files, and this question has wayyyy too many views for the asker's kind of input data to apply to everyone. Parsing CSV is kind of scary since there's no truly official standard, and lots of delimited text writers don't consider edge cases.

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

This question is old, but I believe there's a better solution now that Papa Parseis available. It's a library I wrote, with help from contributors, that parses CSV text or files. It's the only JS library I know of that supports files gigabytes in size. It also handles malformed input gracefully.

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

1 GB file parsed in 1 minute: Parsed 1 GB file in 1 minute

1 分钟内解析 1 GB 文件: 1 分钟解析 1 GB 文件

(Update:With Papa Parse 4, the same file took only about 30 seconds in Firefox. Papa Parse 4 is now the fastest known CSV parserfor the browser.)

更新:使用 Papa Parse 4,相同的文件在 Firefox 中只需要大约 30 秒。Papa Parse 4 现在是浏览器中已知最快的 CSV 解析器。)

Parsing text is very easy:

解析文本非常简单:

var data = Papa.parse(csvString);

Parsing files is also easy:

解析文件也很简单:

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

Streaming files is similar (here's an example that streams a remote file):

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

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

If your web page locks up during parsing, Papa can use web workers to keep your web site reactive.

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

Papa can auto-detect delimiters and match values up with header columns, if a header row is present. It can also turn numeric values into actual number types. It appropriately parses line breaks and quotes and other weird situations, and even handles malformed input as robustly as possible. I've drawn on inspiration from existing libraries to make Papa, so props to other JS implementations.

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

回答by Bimal Grg

I am using d3.jsfor parsing csv file. Very easy to use. Here is the docs.

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

Steps:

脚步:

  • npm install d3-request
  • npm 安装 d3 请求

Using Es6;

使用 Es6;

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

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

Please see docsfor more.

请参阅文档了解更多信息。

Update -d3-request is deprecated. you can use d3-fetch

更新 -不推荐使用 d3-request。你可以使用d3-fetch

回答by Sandro Wiggers

You can use PapaParse to help. https://www.papaparse.com/

您可以使用 PapaParse 来提供帮助。 https://www.papaparse.com/

Here is a CodePen. https://codepen.io/sandro-wiggers/pen/VxrxNJ

这是一个 CodePen。 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; }
        });

回答by curran

Here's a JavaScript function that parses CSV data, accounting for commas found inside quotes.

这是一个解析 CSV 数据的 JavaScript 函数,考虑引号内的逗号。

// 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;                                                      
}

Example use of the function to parse a CSV file that looks like this:

使用该函数解析 CSV 文件的示例,如下所示:

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

into arrays:

成数组:

// 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));

Here's how you can transform the data into objects, like D3's csv parser(which is a solid third party solution):

以下是将数据转换为对象的方法,例如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));

Here's a working fiddle of this code.

是这段代码工作小提琴

Enjoy! --Curran

享受!--柯兰

回答by FredFury

Here is another way to read an external CSV into Javascript(using jQuery).

这是将外部 CSV 读入 Javascript 的另一种方法(使用 jQuery)。

It's a little bit more long winded, but I feel by reading the data into arrays you can exactly follow the process and makes for easy troubleshooting.

这有点冗长,但我觉得通过将数据读入数组,您可以准确地遵循该过程并轻松进行故障排除。

Might help someone else.

可能会帮助别人。

The data file example:

数据文件示例:

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

And here is the code:

这是代码:

$(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]);
    }
})

Hope this helps someone in the future!

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

回答by Gerard ONeill

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;
    }
}

I like to have the regex do as much as possible. This regex treats all items as either quoted or unquoted, followed by either a column delimiter, or a row delimiter. Or the end of text.

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

Which is why that last condition -- without it it would be an infinite loop since the pattern can match a zero length field (totally valid in csv). But since $ is a zero length assertion, it won't progress to a non match and end the loop.

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

And FYI, I had to make the second alternative exclude quotes surrounding the value; seems like it was executing before the first alternative on my javascript engine and considering the quotes as part of the unquoted value. I won't ask -- just got it to work.

仅供参考,我不得不在第二个选项中排除围绕该值的引号;似乎它是在我的 javascript 引擎上的第一个替代方案之前执行的,并将引号视为未引用值的一部分。我不会问 - 只是让它工作。

回答by Adam Grant

Per the accepted answer,

根据接受的答案

I got this to work by changing the 1 to a 0 here:

我通过在此处将 1 更改为 0 来实现此目的:

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

changed to

变成

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

It will compute the a file with one continuous line as having an allTextLines.length of 1. So if the loop starts at 1 and runs as long as it's less than 1, it never runs. Hence the blank alert box.

它将用一条连续线计算一个文件,因为 allTextLines.length 为 1。因此,如果循环从 1 开始并且只要它小于 1 就运行,它永远不会运行。因此,空白的警报框。

回答by Robin Rpr.

If you want to solve this without using Ajax, use the FileReader()Web API.

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

Example implementation:

示例实现:

  1. Select .csvfile
  2. See output
  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>