web-dev-qa-db-fra.com

Comment lire les données d'un fichier * .CSV en utilisant javascript?

Mes données CSV ressemblent à ceci:

rubrique1, rubrique2, rubrique3, rubrique4, rubrique5, valeur1_1, valeur2_1, valeur3_1, valeur4_1, valeur5_1, valeur1_2, valeur2_2, valeur2_2, valeur3_2, valeur4_2, valeur5_2 ....

Comment lisez-vous ces données et les convertissez-vous en un tableau comme celui-ci en utilisant Javascript ?:

[rubrique1: valeur1_1, rubrique2: valeur2_1, rubrique3: valeur3_1, rubrique4: valeur4_1, rubrique5: valeur5_1], [rubrique1: valeur1_2, rubrique2: valeur2_2, rubrique3: valeur3_2, rubrique4: valeur4_2, rubrique5: valeur5_2] ...

J'ai essayé ce code mais pas de chance !:

<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>
169
Mahesh Thumar

REMARQUE: J'ai concocté cette solution avant de me rappeler tous les "cas spéciaux" pouvant se produire dans un fichier CSV valide, tels que des guillemets. Je laisse ma réponse à ceux qui veulent quelque chose de rapide et de sale, mais je recommande réponse d'Evan pour la précision.


Ce code fonctionnera lorsque votre fichier data.txt est une longue chaîne d'entrées séparées par des virgules, sans saut de ligne:

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

Le code suivant fonctionnera sur un "vrai" fichier CSV avec des sauts de ligne entre chaque ensemble d'enregistrements:

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/

108
Blazemonger

Pas besoin d'écrire votre propre ...

La bibliothèque jQuery-CSV possède une fonction appelée $.csv.toObjects(csv) qui effectue automatiquement le mappage.

Remarque: La bibliothèque est conçue pour gérer toutes les données CSV conformes à la norme RFC 418 , y compris tous les cas désagréables d'Edge négligés par la plupart des solutions "simples".

Comme @Blazemonger déjà indiqué, vous devez d’abord ajouter des sauts de ligne pour rendre les données CSV valides.

En utilisant l'ensemble de données suivant:

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

Utilisez le code:

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

La sortie enregistrée dans 'data' sera:

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

Remarque: Techniquement, la façon dont vous avez écrit le mappage clé-valeur est JavaScript invalide. Les objets contenant les paires clé-valeur doivent être entourés de crochets.

Si vous voulez l'essayer vous-même, je vous suggère de jeter un coup d'œil à la démonstration de l'utilisation de base sous l'onglet "toObjects ()".

Avertissement: je suis l'auteur original de jQuery-CSV.

Mise à jour:

Édité pour utiliser l'ensemble de données fourni par l'opération et inclure un lien vers la démonstration où les données peuvent être testées pour en vérifier la validité.

Update2:

En raison de la fermeture de Google Code. jquery-csv a été déplacé dans GitHub

192
Evan Plaice

Ne séparez pas les virgules - cela ne fonctionnera pas pour la plupart des fichiers CSV, et cette question a beaucoup trop de points de vue pour que le type de données d'entrée du demandeur s'applique à tout le monde. L'analyse du format CSV est assez effrayante, car il n'existe pas de norme vraiment officielle et de nombreux auteurs de texte délimité ne prennent pas en compte les cas Edge.

Cette question est ancienne, mais je pense qu'il existe une meilleure solution maintenant que Papa Parse est disponible. C'est une bibliothèque que j'ai écrite, avec l'aide de contributeurs, qui analyse le texte ou les fichiers CSV. C'est la seule bibliothèque JS que je connaisse qui supporte des fichiers d'une taille de 1 Go. Il gère également les entrées mal formées avec élégance.

Fichier de 1 Go analysé en 1 minute: Parsed 1 GB file in 1 minute

( Mise à jour: Avec Papa Parse 4, le même fichier ne prenait qu’environ 30 secondes sous Firefox. Papa Parse 4 est maintenant le CSV le plus rapide connu du monde) analyseur pour le navigateur.)

L'analyse du texte est très facile:

var data = Papa.parse(csvString);

L'analyse des fichiers est également facile:

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

La diffusion de fichiers est similaire (voici un exemple qui diffuse un fichier distant):

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

Si votre page Web se bloque pendant l'analyse, Papa peut utiliser des travailleurs Web pour que votre site Web reste réactif.

Papa peut détecter automatiquement les délimiteurs et faire correspondre les valeurs aux colonnes d'en-tête, si une ligne d'en-tête est présente. Il peut également transformer des valeurs numériques en types de nombres réels. Il analyse de manière appropriée les sauts de ligne, les guillemets et autres situations étranges, et traite même les entrées malformées aussi robustement que possible. Je me suis inspiré des bibliothèques existantes pour créer Papa, donc des accessoires pour d'autres implémentations de JS.

61
Matt

J'utilise d3.js pour analyser le fichier csv. Très facile à utiliser. Voici le docs .

Pas:

  • npm install d3-request

En utilisant Es6;

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

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

S'il vous plaît voir docs pour plus.

Update - d3-request est obsolète. vous pouvez utiliser d3-fetch

7
Bimal Grg

Voici une fonction JavaScript qui analyse les données CSV, en tenant compte des virgules trouvées entre guillemets.

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

Exemple d'utilisation de la fonction pour analyser un fichier CSV ressemblant à ceci:

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

en tableaux:

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

Voici comment vous pouvez transformer les données en objets, comme l’analyseur csv de D (une solution tierce solide):

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

Voici un violon de travail de ce code .

Prendre plaisir! -- Curran

3
curran

Selon le réponse acceptée ,

J'ai obtenu ceci en changeant le 1 en 0 ici:

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

changé en

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

Il calculera le fichier a avec une ligne continue comme ayant un allTextLines.length de 1. Ainsi, si la boucle commence à 1 et s'exécute tant qu'elle est inférieure à 1, elle ne s'exécutera jamais. D'où le champ d'alerte vide.

1
Adam Grant
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;
    }
}

J'aime que la regex en fasse autant que possible. Cette expression rationnelle traite tous les éléments entre guillemets ou non, suivis par un délimiteur de colonne ou un délimiteur de ligne. Ou la fin du texte.

C’est la raison pour laquelle cette dernière condition - sans elle, ce serait une boucle infinie puisque le modèle peut correspondre à un champ de longueur nulle (totalement valide dans csv). Mais puisque $ est une assertion de longueur nulle, il ne progressera pas et ne mettra pas fin à la boucle.

Et pour info, je devais faire la deuxième alternative, exclure les citations entourant la valeur; semble avoir été exécuté avant la première alternative sur mon moteur javascript et en considérant les guillemets comme faisant partie de la valeur non mise entre guillemets. Je ne demanderai pas - je viens de le faire fonctionner.

1
Gerard ONeill

Voici un autre moyen de lire un fichier CSV externe en Javascript (en utilisant jQuery).

C'est un peu plus long, mais je pense qu'en lisant les données dans des tableaux, vous pouvez suivre exactement le processus et faciliter le dépannage.

Peut aider quelqu'un d'autre.

Exemple de fichier de données:

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

Et voici le 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]);
    }
})

J'espère que cela aidera quelqu'un dans le futur!

1
FredFury

Vous pouvez utiliser PapaParse pour vous aider. https://www.papaparse.com/

Voici un 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; }
        });
1
Sandro Wiggers