Wie lese ich Daten aus einer * .CSV-Datei mit Javascript?

192

Meine CSV-Daten sehen folgendermaßen aus:

Überschrift1, Überschrift2, Überschrift3, Überschrift4, Überschrift5, Wert1_1, Wert2_1, Wert3_1, Wert4_1, Wert5_1, Wert1_2, Wert2_2, Wert3_2, Wert4_2, Wert5_2 ....

Wie liest man diese Daten und konvertiert sie mit Javascript in ein Array wie dieses?:

[Überschrift1: Wert1_1, Überschrift2: Wert2_1, Überschrift3: Wert3_1, Überschrift4: Wert4_1, Überschrift5: Wert5_1], [Überschrift1: Wert1_2, Überschrift2: Wert2_2, Überschrift3: Wert3_2, Überschrift4: Wert4_2, Überschrift5: Wert5_2] ....

Ich habe diesen Code ausprobiert, aber kein Glück!:

<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>
Mahesh Thumar
quelle
Ohne Zeilenumbrüche in Ihrer CSV-Datei kann kein JavaScript-Code erkennen, wo ein Array (oder Objekt) stoppt und das andere beginnt (es sei denn, Sie wissen im Voraus, dass es immer genau fünf Überschriften gibt). War das ein Versehen beim Ausschneiden und Einfügen?
Blazemonger
Ja, ich weiß im Voraus, dass es genau fünf Felder gibt.
Mahesh Thumar
1
Nächste Frage: Ist jQuery in der Lösung zulässig? Sie haben das Tag verwendet, aber Ihr Beispielcode ist reines JavaScript.
Blazemonger
Ja, jQuery ist erlaubt. Deshalb füge ich es in Tag ein.
Mahesh Thumar
1
Ich denke nicht, dass die Verwendung von file://...erlaubt ist XMLHttpRequest.
Noel Llevares

Antworten:

118

HINWEIS: Ich habe diese Lösung entwickelt, bevor ich an alle "Sonderfälle" erinnert wurde, die in einer gültigen CSV-Datei auftreten können, z. B. maskierte Anführungszeichen. Ich überlasse meine Antwort denen, die etwas schnelles und schmutziges wollen, aber ich empfehle Evans Antwort aus Gründen der Genauigkeit.


Dieser Code funktioniert, wenn Ihre data.txtDatei eine lange Folge von durch Kommas getrennten Einträgen ohne Zeilenumbrüche enthält:

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

Der folgende Code funktioniert für eine "echte" CSV-Datei mit Zeilenumbrüchen zwischen den einzelnen Datensätzen:

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/

Blazemonger
quelle
4
Dies setzt übrigens voraus, dass die CSV-Datei tatsächlich mehrere Zeilen enthält - darauf wird allText.split(/\r\n|\n/)aufgeteilt. Wenn alle Ihre Daten tatsächlich eine lange Folge von durch Kommas getrennten Daten ohne Zeilenumbrüche sind, handelt es sich nicht um eine echte CSV-Datei.
Blazemonger
1
Hallo, ich habe diesen Code verwendet: Aber es gibt keine Ausgabe. Es wird nur eine leere Warnung angezeigt. Meine Datei sieht folgendermaßen aus: Überschrift1, Überschrift2, Überschrift3, Überschrift4, Überschrift5, Wert1_1, Wert2_1, Wert3_1, Wert4_1, Wert5_1, Wert1_2, Wert2_2, Wert3_2, Wert4_2, Wert5_2 Sowohl csv.html als auch data.txt befinden sich im selben Ordner
Mahesh Thumar
Wenn dies keine korrekte Datei (oder Daten) ist, wie sollte meine Datei dann aussehen?
Mahesh Thumar
7
Der Code verarbeitet möglicherweise nicht alle gültigen IETF-Standard-CSV-Dateien und schlägt möglicherweise fehl, wenn Zeichenfolgen mit eingebetteten Kommas, Zeilenumbrüchen oder doppelten Anführungszeichen vorhanden sind. Dies 1, "IETF allows ""quotes"", commas and \nline breaks"ist beispielsweise zulässig, da die Zeichenfolge von doppelten Anführungszeichen umgeben ist und die doppelten Anführungszeichen maskiert werden.
Prototyp
1
Ich habe versucht, eine CSV-Datei von einem Mac zu lesen. Ich konnte dieses Skript nur dazu bringen, Zeilenumbrüche zu erkennen, als ich die erste Aufteilung in diese änderte. var allTextLines = allText.split("\r"); Danach funktionierte es großartig! Vielen Dank!
Joe
204

Sie müssen keine eigenen schreiben ...

Die jQuery-CSV- Bibliothek verfügt über eine Funktion namens $.csv.toObjects(csv), die das Mapping automatisch durchführt.

Hinweis: Die Bibliothek ist für die Verarbeitung von CSV-Daten ausgelegt, die RFC 4180- kompatibel sind, einschließlich aller unangenehmen Randfälle, die die meisten "einfachen" Lösungen übersehen.

Wie bereits bei @Blazemonger erwähnt, müssen Sie zuerst Zeilenumbrüche hinzufügen, damit die Daten als CSV gültig sind.

Verwenden des folgenden Datensatzes:

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

Verwenden Sie den Code:

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

Die in 'Daten' gespeicherte Ausgabe lautet:

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

Hinweis: Technisch gesehen ist die Art und Weise, wie Sie die Schlüsselwertzuordnung geschrieben haben, ungültiges JavaScript. Die Objekte, die die Schlüssel-Wert-Paare enthalten, sollten in Klammern gesetzt werden.

Wenn Sie es selbst ausprobieren möchten, empfehlen wir Ihnen, sich die Demonstration der grundlegenden Verwendung auf der Registerkarte 'toObjects ()' anzusehen.

Haftungsausschluss: Ich bin der ursprüngliche Autor von jQuery-CSV.

Aktualisieren:

Bearbeitet, um den Datensatz zu verwenden, den die Operation bereitgestellt hat, und enthält einen Link zur Demo, in der die Daten auf ihre Gültigkeit getestet werden können.

Update2:

Aufgrund der Verschalung von Google Code. jquery-csv ist zu GitHub gewechselt

Evan Scholle
quelle
3
IOW, "toObject" ist oder kann als "toJSON" angesehen werden, nein? Und ist der Doppelpunkt nach dem Aufruf von toObjects (csv) ein Tippfehler? IOW, sollte das nicht ein Semikolon sein?
B. Clay Shannon
11
Ist CSV ein Dateiname?
Blase
10
Fantastische Bibliothek. Zu Ihrer Information, der übergebene Parameter csvist eine CSV-Zeichenfolge. Lesen Sie die CSV-Datei als Text, um die CSV-Zeichenfolge abzurufen.
Callmekatootie
3
@Evan Plaice Wie verwende ich diese Bibliothek zum Lesen aus einer CSV-Datei?
Richa Sinha
1
@RichaSinha Liest die Datei als Textpuffer über die HTML5-Datei-API oder AJAX ein. Übergeben Sie dann den Zeichenfolgenpuffer an den Parser. Infolgedessen wird eine Reihe von Daten ausgespuckt. Beispiele finden Sie auf der Projektseite.
Evan Plaice
75

Nicht durch Kommas teilen - es funktioniert nicht für die meisten CSV-Dateien, und diese Frage hat viel zu viele Ansichten, als dass die Art der Eingabedaten des Fragestellers für alle gelten könnte. Das Parsen von CSV ist beängstigend, da es keinen wirklich offiziellen Standard gibt und viele abgegrenzte Textschreiber Randfälle nicht berücksichtigen.

Diese Frage ist alt, aber ich glaube, es gibt jetzt eine bessere Lösung, da Papa Parse verfügbar ist. Es ist eine Bibliothek, die ich mit Hilfe von Mitwirkenden geschrieben habe und die CSV-Texte oder -Dateien analysiert. Es ist die einzige mir bekannte JS-Bibliothek, die Dateien mit einer Größe von Gigabyte unterstützt. Es behandelt auch fehlerhafte Eingaben ordnungsgemäß.

1 GB Datei in 1 Minute analysiert: Analysierte 1 GB Datei in 1 Minute

( Update: Mit Papa Parse 4 dauerte dieselbe Datei in Firefox nur etwa 30 Sekunden. Papa Parse 4 ist jetzt der schnellste bekannte CSV-Parser für den Browser.)

Das Parsen von Text ist sehr einfach:

var data = Papa.parse(csvString);

Das Parsen von Dateien ist ebenfalls einfach:

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

Das Streamen von Dateien ist ähnlich (hier ein Beispiel zum Streamen einer Remote-Datei):

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

Wenn Ihre Webseite während des Parsens blockiert, kann Papa Web-Worker verwenden, um Ihre Website reaktiv zu halten.

Papa kann Trennzeichen automatisch erkennen und Werte mit Kopfspalten abgleichen, wenn eine Kopfzeile vorhanden ist. Es kann auch numerische Werte in tatsächliche Zahlentypen umwandeln. Es analysiert Zeilenumbrüche und Anführungszeichen und andere seltsame Situationen angemessen und verarbeitet sogar fehlerhafte Eingaben so robust wie möglich. Ich habe mich von vorhandenen Bibliotheken inspirieren lassen, um Papa zu erstellen, also Requisiten für andere JS-Implementierungen.

Matt
quelle
Papa ist einfach zu bedienen und schnell! Vielen Dank!
Technotronic
+1 Gute Arbeit bei Papa Parse. Ich möchte es eines Tages im Detail studieren, um zu sehen, wie Sie mit großen Dateien und Streaming umgegangen sind. Ich freue mich sehr, dass andere Entwickler voll funktionsfähige Parser schreiben, die dort weitermachen, wo jquery-csv aufgehört hat.
Evan Plaice
3
@EvanPlaice Danke. Diese Präsentation, die ich gestern Abend bei einem lokalen Treffen gehalten habe, könnte Ihnen
Matt
1
@ Matt Das war eine großartige Präsentation, die verständnisvoller über Papa Parse beschreibt
Siva
1
@ Malky.Kid Das ist keine gültige CSV (dh Leerzeichen in einem nicht begrenzten Wert sind nicht gut). Die Implementierung des CSV-Formats von MS Excel ist zum Kotzen. Wenn Sie weiterhin Zugriff auf die Quelldatei haben, sollte es eine Option zum Aktivieren von Anführungszeichen geben. Sobald Sie dies tun, sollten Ihre Daten mit jedem CSV-Parser funktionieren.
Evan Plaice
9

Ich verwende d3.js zum Parsen von CSV-Dateien. Sehr einfach zu bedienen. Hier sind die Dokumente .

Schritte:

  • npm installiere d3-request

Verwenden von Es6;

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

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

Weitere Informationen finden Sie in den Dokumenten .

Update - d3-Anfrage ist veraltet. Sie können d3-fetch verwenden

Bimal Grg
quelle
4

Sie können PapaParse verwenden, um zu helfen. https://www.papaparse.com/

Hier ist ein 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; }
        });
Sandro Wiggers
quelle
3

Hier ist eine JavaScript-Funktion, die CSV-Daten analysiert und Kommas in Anführungszeichen berücksichtigt.

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

Beispiel für die Verwendung der Funktion zum Parsen einer CSV-Datei, die folgendermaßen aussieht:

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

So können Sie die Daten in Objekte umwandeln, z. B. den CSV-Parser von D3 (eine solide Lösung von Drittanbietern):

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 ist eine funktionierende Geige dieses Codes .

Genießen! - Curran

curran
quelle
1

Hier ist eine andere Möglichkeit, eine externe CSV in Javascript zu lesen (mit jQuery).

Es ist etwas langwieriger, aber ich denke, wenn Sie die Daten in Arrays einlesen, können Sie den Prozess genau verfolgen und die Fehlerbehebung vereinfachen.

Könnte jemand anderem helfen.

Das Beispiel für eine Datendatei:

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

Und hier ist der 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]);
    }
})

Hoffe das hilft jemandem in der Zukunft!

FredFury
quelle
Hallo aus der Zukunft, also habe ich diese Antwort ausprobiert und es fehlte ein )Zeichen in Zeile 45, also habe ich es hinzugefügt, aber jetzt in Zeile 9 gibt es mir einen Konsolenfehler. Uncaught ReferenceError: $ is not defined at index.html:9Könnten Sie dabei helfen?
Lasagne Cat
1
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;
    }
}

Ich möchte, dass der Regex so viel wie möglich macht. Diese Regex behandelt alle Elemente entweder als Anführungszeichen oder als Anführungszeichen, gefolgt von einem Spalten- oder Zeilenbegrenzer. Oder das Ende des Textes.

Aus diesem Grund ist diese letzte Bedingung - ohne sie wäre es eine Endlosschleife, da das Muster mit einem Feld mit der Länge Null übereinstimmen kann (vollständig gültig in CSV). Da $ jedoch eine Behauptung mit der Länge Null ist, wird es nicht zu einer Nichtübereinstimmung übergehen und die Schleife beenden.

Und zu Ihrer Information, ich musste die zweite Alternative dazu bringen, Anführungszeichen auszuschließen, die den Wert umgeben. Es scheint, als ob es vor der ersten Alternative auf meiner Javascript-Engine ausgeführt wurde und die Anführungszeichen als Teil des nicht zitierten Werts betrachtet. Ich werde nicht fragen - habe es gerade zum Laufen gebracht.

Gerard ONeill
quelle
Leider bin ich mit dieser Funktion in eine Endlosschleife geraten.
Hauke
@Hauke ​​- Wenn Sie die Daten in ein paar Spalten und Zeilen aufteilen könnten, die immer noch die Endlosschleife erzeugen, würde ich es begrüßen - es könnte mir einen Einblick geben, warum ich zuvor versagt habe.
Gerard ONeill
1

Per die akzeptierte Antwort ,

Ich habe das zum Laufen gebracht, indem ich hier die 1 in eine 0 geändert habe:

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

gewechselt zu

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

Die a-Datei mit einer durchgehenden Zeile wird mit einer allTextLines.length von 1 berechnet. Wenn die Schleife also bei 1 beginnt und so lange ausgeführt wird, wie sie kleiner als 1 ist, wird sie nie ausgeführt. Daher das leere Warnfeld.

Adam Grant
quelle
0

Wenn Sie dies ohne Verwendung von Ajax lösen möchten , verwenden Sie die FileReader()Web-API .

Beispielimplementierung:

  1. .csvDatei auswählen
  2. Siehe Ausgabe

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>

Robin Rpr.
quelle
0
$(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]);

                        }
                      }
                    }
rahul kulkarni
quelle
Während dieser Code die Frage lösen kann, einschließlich einer Erklärung, wie und warum dies das Problem löst, würde dies wirklich dazu beitragen, die Qualität Ihres Beitrags zu verbessern, und wahrscheinlich zu mehr Up-Votes führen. Denken Sie daran, dass Sie in Zukunft die Frage für die Leser beantworten, nicht nur für die Person, die jetzt fragt. Bitte bearbeiten Sie Ihre Antwort, um Erklärungen hinzuzufügen und anzugeben, welche Einschränkungen und Annahmen gelten. Aus der Überprüfung
doppelter Piepton