Hoe lees ik gegevens uit een *.CSV-bestand met javascript?

Mijn csv-gegevens zien er als volgt uit:

kop1,kop2,kop3,kop4,kop5,waarde1_1,waarde2_1,waarde3_1,waarde4_1,waarde5_1,waarde1_2,waarde2_2,waarde3_2,waarde4_2,waarde5_2….

Hoe lees je deze gegevens en converteer je ze naar een array als deze met Javascript?:

[kop1:waarde1_1 , kop2:waarde2_1, kop3 : waarde3_1, kop4
: waarde4_1, kop5 : waarde5_1 ],[kop1:waarde1_2 ,
rubriek2:waarde2_2, rubriek3: waarde3_2, rubriek4: waarde4_2, rubriek5
: waarde5_2 ]….

Ik heb deze code geprobeerd, maar geen geluk!:

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

Antwoord 1, autoriteit 100%

OPMERKING:ik heb deze oplossing bedacht voordat ik werd herinnerd aan alle “speciale gevallen” die kunnen voorkomen in een geldig CSV-bestand, zoals aanhalingstekens met escapetekens. Ik laat mijn antwoord achter voor degenen die iets snel en vies willen, maar ik raad Evan’s antwoordaan voor nauwkeurigheid.


Deze code werkt wanneer uw data.txt-bestand één lange reeks door komma’s gescheiden items is, zonder nieuwe regels:

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

De volgende code werkt op een “echt” CSV-bestand met regeleinden tussen elke set records:

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/


Antwoord 2, autoriteit 95%

U hoeft niet uw eigen te schrijven…

De jQuery-CSVbibliotheek heeft een functie genaamd $.csv.toObjects(csv)die de mapping automatisch uitvoert.

Opmerking: de bibliotheek is ontworpen om alle CSV-gegevens te verwerken die RFC 4180zijn compliant, inclusief alle vervelende randgevallen die de meeste ‘eenvoudige’ oplossingen over het hoofd zien.

Zoals @Blazemonger al zei, moet u eerst regeleinden toevoegen om de gegevens geldig CSV te maken.

De volgende dataset gebruiken:

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

Gebruik de code:

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

De uitvoer die wordt opgeslagen in ‘data’ is:

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

Opmerking: technisch gezien is de manier waarop u de sleutel/waarde-toewijzing hebt geschreven ongeldig JavaScript. De objecten die de sleutel-waardeparen bevatten, moeten tussen haakjes worden geplaatst.

Als je het zelf wilt uitproberen, raad ik je aan een kijkje te nemen op de Demonstratie van basisgebruikonder het tabblad ‘toObjects()’.

Disclaimer: ik ben de oorspronkelijke auteur van jQuery-CSV.

Bijwerken:

Bewerkt om de dataset te gebruiken die de op heeft geleverd en bevat een link naar de demo waar de gegevens op geldigheid kunnen worden getest.

Update2:

Vanwege het sluiten van Google Code. jquery-csv is verhuisd naar GitHub


Antwoord 3, autoriteit 66%

Niet splitsen op komma’s — het werkt niet voor de meeste CSV-bestanden, en deze vraag heeft veel te veel weergaven om het soort invoergegevens van de vrager op iedereen te kunnen toepassen. Het ontleden van CSV is een beetje eng omdat er geen echt officiële standaard is, en veel tekstschrijvers met scheidingstekens houden geen rekening met randgevallen.

Deze vraag is oud, maar ik geloof dat er een betere oplossing is nu Papa Parsebeschikbaar is. Het is een bibliotheek die ik heb geschreven, met hulp van bijdragers, die CSV-tekst of bestanden parseert. Het is de enige JS-bibliotheek die ik ken die bestanden in gigabytes ondersteunt. Het verwerkt ook op een elegante manier verkeerd opgemaakte invoer.

1 GB-bestand geparseerd in 1 minuut:
1 GB bestand in 1 minuut geparseerd

(Update:Met Papa Parse 4 duurde hetzelfde bestand slechts ongeveer 30 seconden in Firefox. Papa Parse 4 is nu de snelst bekende CSV-parservoor de browser.)

Het ontleden van tekst is heel eenvoudig:

var data = Papa.parse(csvString);

Bestanden ontleden is ook eenvoudig:

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

Het streamen van bestanden is vergelijkbaar (hier is een voorbeeld dat een extern bestand streamt):

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

Als uw webpagina vastloopt tijdens het parseren, kan Papa webwerkers gebruiken om uw website reactief te houden.

Papa kan automatisch scheidingstekens detecteren en waarden matchen met kopkolommen, als er een koprij aanwezig is. Het kan ook numerieke waarden omzetten in werkelijke nummertypen. Het ontleedt op de juiste manier regeleinden en aanhalingstekens en andere rare situaties, en behandelt zelfs misvormde invoer zo robuust mogelijk. Ik heb inspiratie gehaald uit bestaande bibliotheken om Papa te maken, dus rekwisieten voor andere JS-implementaties.


Antwoord 4, autoriteit 9%

Ik gebruik d3.jsvoor het ontleden van het csv-bestand. Zeer gemakkelijk te gebruiken.
Hier zijn de docs.

Stappen:

  • npm install d3-request

Es6 gebruiken;

import { csv } from 'd3-request';
import url from 'path/to/data.csv';
csv(url, function(err, data) {
 console.log(data);
})

Zie docsvoor meer informatie.

Bijwerken –
d3-verzoek is verouderd. je kunt d3-fetch

gebruiken


Antwoord 5, autoriteit 4%

Hier is een JavaScript-functie die CSV-gegevens parseert, rekening houdend met komma’s tussen aanhalingstekens.

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

Voorbeeld van gebruik van de functie om een ​​CSV-bestand te ontleden dat er als volgt uitziet:

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

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

Hier leest u hoe u de gegevens kunt omzetten in objecten, zoals D3’s csv-parser(die is een solide oplossing van derden):

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

Hier is een werkende viool van deze code.

Veel plezier! —Curran


Antwoord 6, autoriteit 3%

Je kunt PapaParse gebruiken om te helpen.
https://www.papaparse.com/

Hier is een 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; }
        });

Antwoord 7, autoriteit 2%

Als je dit wilt oplossen zonder Ajaxte gebruiken , gebruik de FileReader()Web API.

Voorbeeld implementatie:

  1. Selecteer .csvbestand
  2. Bekijk uitvoer
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>

Antwoord 8, autoriteit 2%

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

Ik wil graag dat de regex zoveel mogelijk doet. Deze regex behandelt alle items als tussen aanhalingstekens of niet-aanhalingstekens, gevolgd door een kolomscheidingsteken of een rijscheidingsteken. Of het einde van de tekst.

Dat is de reden waarom die laatste voorwaarde — zonder deze zou het een oneindige lus zijn, aangezien het patroon kan overeenkomen met een veld met lengte nul (helemaal geldig in csv). Maar aangezien $ een bewering met een lengte van nul is, zal het niet doorgaan naar een non-match en de lus beëindigen.

En ter informatie, ik moest ervoor zorgen dat het tweede alternatief de aanhalingstekens rond de waarde uitsluit; het lijkt erop dat het vóór het eerste alternatief op mijn javascript-engine werd uitgevoerd en de aanhalingstekens als onderdeel van de niet-geciteerde waarde beschouwde. Ik zal het niet vragen — ik heb het net werkend gekregen.


Antwoord 9

Hier is een andere manier om een externe CSV in Javascript in te lezen(met jQuery).

Het is een beetje langdradig, maar ik heb het gevoel dat door de gegevens in arrays te lezen, je het proces precies kunt volgen en dat het gemakkelijk is om problemen op te lossen.

Misschien iemand anders helpen.

Het voorbeeld van het gegevensbestand:

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

En hier is de 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]);
    }
})

Ik hoop dat dit iemand in de toekomst helpt!


Antwoord 10

Volgens het geaccepteerde antwoord,

Ik heb dit laten werken door de 1 hier in een 0 te veranderen:

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

veranderd in

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

Het berekent het bestand met één doorlopende regel als een allTextLines.length van 1. Dus als de lus begint bij 1 en loopt zolang deze kleiner is dan 1, wordt hij nooit uitgevoerd. Vandaar het lege waarschuwingsvenster.


Antwoord 11

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

Antwoord 12

Eigenlijk kunt u een lichtgewicht bibliotheek gebruiken met de naam any-text.

  • afhankelijkheden installeren
npm i -D any-text
  • gebruik een aangepast commando om bestanden te lezen
var reader = require('any-text');
reader.getText(`path-to-file`).then(function (data) {
  console.log(data);
});

of gebruik async-wait :

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

Antwoord 13

Een beetje laat, maar ik hoop dat iemand er iets aan heeft.

Enige tijd geleden had ik zelfs een probleem waarbij de stringgegevens \nertussen bevatten en tijdens het lezen van het bestand als verschillende regels werden gelezen.

Bijvoorbeeld

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

Tijdens het lezen:

Harry
Potter,21,Gryffindor

Ik had een bibliotheek csvtojsongebruikt in mijn hoekige project om dit probleem op te lossen.

Je kunt het CSV-bestand als een string lezen met behulp van de volgende code en die string vervolgens doorgeven aan de csvtojson-bibliotheek en je krijgt dan een lijst met JSON.

Voorbeeldcode:

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

Antwoord 14

Ik gebruik de jquery-csvom dit te doen.

evanplaice/jquery-csv

en ik geef twee voorbeelden zoals hieronder

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>

Other episodes