簡體   English   中英

如何使用 JavaScript 從 *.CSV 文件中讀取數據?

[英]How to read data From *.CSV file using JavaScript?

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

不用自己寫...

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):

保存在“數據”中的輸出將是:

[
  { 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 的原作者。

更新:

編輯為使用操作提供的數據集,並包含指向演示的鏈接,可以在其中測試數據的有效性。

更新2:

由於谷歌代碼的關閉。 jquery-csv 已移至 GitHub

注意:在提醒我有效 CSV 文件中可能出現的所有“特殊情況”(如轉義引號)之前,我編寫了此解決方案。 我將把我的答案留給那些想要快速和骯臟的人,但我推薦Evan 的答案以確保准確性。


當您的data.txt文件是一長串以逗號分隔的條目且沒有換行符時,此代碼將起作用:

數據.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 文件:

數據.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/

不要以逗號分隔 - 它不適用於大多數 CSV 文件,而且這個問題對於提問者的輸入數據類型有太多視圖,無法應用於每個人。 解析 CSV 有點嚇人,因為沒有真正的官方標准,而且許多分隔文本作者不考慮邊緣情況。

這個問題很老,但我相信現在有更好的解決方案Papa Parse可用。 這是我在貢獻者的幫助下編寫的一個庫,用於解析 CSV 文本或文件。 它是我所知道的唯一一個支持千兆字節大小的文件的 JS 庫。 它還可以優雅地處理格式錯誤的輸入。

1 分鍾解析 1 GB 文件:1 分鍾解析 1 GB 文件

更新:使用 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 實現的道具。

我正在使用d3.js來解析 csv 文件。 非常容易使用。 這是文檔

腳步:

  • npm install 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

這是一個解析 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;                                                      
}

使用該函數解析如下所示的 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));

是此代碼的工作小提琴

享受! ——柯倫

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

這是一個 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; }
        });

如果您想在不使用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 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 引擎上的第一個替代方案之前執行,並將引號視為未引用值的一部分。 我不會問 - 只是讓它工作。

根據接受的答案

我通過在此處將 1 更改為 0 來實現此功能:

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

變成

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

它將計算一個具有連續行的文件,因為它的 allTextLines.length 為 1。因此,如果循環從 1 開始並且只要它小於 1 就運行,它永遠不會運行。 因此,空白警報框。

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

                        }
                      }
                    }

實際上,您可以使用一個名為any-text的輕量級庫。

  • 安裝依賴項
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');
  });
});

這是另一種將外部 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]);
    }
})

希望這對將來的人有所幫助!

有點晚了,但我希望它可以幫助某人。

前段時間,我什至遇到了一個問題,即字符串數據在兩者之間包含\n ,而在讀取它用來讀取不同行的文件時。

例如。

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

在讀的時候:

Harry
Potter,21,Gryffindor

我在我的角度項目中使用了一個庫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是數據處理的最佳替代方案之一。 它是開源的並且可以免費使用,但它也是模塊化的,所以我們可以只導入fetch 模塊

這是一個基本的例子。 我們將使用傳統模式,因此我將導入整個D3庫。 現在,讓我們調用d3.csv function 就完成了。 這個function內部調用了fetch方法,因此可以打開dataURL、url、文件、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>

如果我們不想使用任何庫,而只想使用 pain JavaScrip (Vanilla JS),並且我們設法將文件的文本內容作為data ,並且不想使用d3 ,我們可以實現一個簡單的 function這會將data拆分為text數組,然后我們將提取第一行並拆分為headers數組, text的 rest 將是我們將處理的lines 之后,我們 map 每一line並提取其values ,並從一個數組中創建row object,該數組是通過將每個header映射到values[index]中的對應值而創建的。

筆記:

我們還要使用一個小技巧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})

最后,讓我們使用 fetch 和解析 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>

我用這個文件來測試它

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM