Bagaimana cara membaca data Dari file * .CSV menggunakan javascript?


196

Data csv saya terlihat seperti ini:

heading1, heading2, heading3, heading4, heading5, value1_1, value2_1, value3_1, value4_1, value5_1, value1_2, value2_2, value3_2, value4_2, value4_2, value5_2 ....

Bagaimana Anda membaca data ini dan mengkonversi ke array seperti ini menggunakan 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] ....

Saya sudah mencoba kode ini tetapi tidak berhasil !:

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

Tanpa jeda baris dalam file CSV Anda, tidak mungkin bagi kode JavaScript untuk mengetahui di mana satu array (atau objek) berhenti dan yang lainnya dimulai (kecuali Anda tahu sebelumnya bahwa selalu ada tepat lima pos). Apakah ini pengawasan cut-and-paste?
Blazemonger

Ya, saya tahu sebelumnya bahwa ada Lima Bidang Tepat.
Mahesh Thumar

1
Pertanyaan selanjutnya: apakah jQuery diizinkan dalam solusi? Anda menggunakan tag tetapi kode sampel Anda adalah JavaScript murni.
Blazemonger

ya, jQuery diizinkan, Itu sebabnya saya memasukkannya ke dalam Tag.
Mahesh Thumar

1
Saya tidak berpikir penggunaan file://...diizinkan XMLHttpRequest.
Noel Llevares

Jawaban:


118

CATATAN: Saya membuat solusi ini sebelum saya diingatkan tentang semua "kasus khusus" yang dapat terjadi dalam file CSV yang valid, seperti kutipan yang lolos. Saya meninggalkan jawaban saya untuk mereka yang menginginkan sesuatu yang cepat dan kotor, tetapi saya merekomendasikan jawaban Evan untuk akurasi.


Kode ini akan berfungsi ketika data.txtfile Anda adalah satu string panjang entri yang dipisahkan koma, tanpa baris baru:

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

Kode berikut akan berfungsi pada file CSV "benar" dengan linebreak di antara setiap set catatan:

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/


4
By the way, ini mengasumsikan bahwa file CSV sebenarnya memiliki beberapa baris - itulah yang allText.split(/\r\n|\n/)dibelah. Jika semua data Anda sebenarnya adalah satu string panjang dari data yang dipisahkan koma tanpa baris baru, itu bukan file CSV nyata.
Blazemonger

1
Hai Saya sudah menggunakan Kode ini: Tapi tidak ada output Hanya peringatan kosong yang ditampilkan. file saya terlihat seperti: heading1, heading2, heading3, heading4, heading5, value1_1, value2_1, value3_1, value4_1, value1_2, value2_2, value3_2, value4_2, value5_2 Baik csv.html dan data.txt ada di folder yang sama
Mahesh Thumar

Jika ini bukan file yang benar (atau data) lalu bagaimana seharusnya file saya terlihat ??
Mahesh Thumar

7
Kode ini mungkin tidak menangani semua file CSV standar IETF yang valid, dan mungkin gagal jika ada string yang telah menyematkan koma, jeda baris atau tanda kutip ganda. Misalnya, 1, "IETF allows ""quotes"", commas and \nline breaks"yang diizinkan karena string dikelilingi dengan tanda kutip ganda, dan tanda kutip ganda itu lolos.
prototipe

1
Saya mencoba membaca file .csv dari mac. Saya hanya bisa membuat skrip ini mengenali karakter baris baru ketika saya mengubah pemisahan pertama menjadi ini. var allTextLines = allText.split("\r"); Setelah itu, itu berhasil! Terima kasih!
Joe

207

Tidak perlu menulis sendiri ...

The jQuery-CSV perpustakaan memiliki fungsi yang disebut $.csv.toObjects(csv)yang melakukan pemetaan secara otomatis.

Catatan: Perpustakaan dirancang untuk menangani data CSV apa pun yang sesuai dengan RFC 4180 , termasuk semua kasing tepi yang buruk yang diabaikan oleh sebagian besar solusi 'sederhana'.

Seperti @Blazemonger sudah menyatakan, pertama Anda perlu menambahkan jeda baris untuk membuat CSV data yang valid.

Menggunakan dataset berikut:

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

Gunakan kode:

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

Output yang disimpan dalam 'data' adalah:

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

Catatan: Secara teknis, cara Anda menulis pemetaan nilai kunci adalah JavaScript yang tidak valid. Objek yang berisi pasangan nilai kunci harus dibungkus dengan tanda kurung.

Jika Anda ingin mencobanya sendiri, saya sarankan Anda melihat Demonstrasi Penggunaan Dasar di bawah tab 'toObjects ()'.

Penafian: Saya penulis asli jQuery-CSV.

Memperbarui:

Diedit untuk menggunakan dataset yang disediakan oleh op dan menyertakan tautan ke demo tempat data dapat diuji validitasnya.

Pembaruan2:

Karena penutupan Kode Google. jquery-csv telah pindah ke GitHub


3
TKI, "toObject" adalah atau dapat dianggap sebagai "toJSON", bukan? Dan, apakah titik dua mengikuti panggilan toObjects (csv) salah ketik? TKI, bukankah itu seharusnya titik koma?
B. Clay Shannon

11
Apakah CSV nama file?
gelembung

10
Perpustakaan yang fantastis. FYI, parameter yang csvdilewatkan adalah string csv - baca file csv sebagai teks untuk mendapatkan string csv.
callmekatootie

3
@Evan Plaice Cara menggunakan perpustakaan ini untuk membaca dari file csv?
Richa Sinha

1
@RichaSinha Baca file sebagai buffer teks melalui API File HTML5 atau AJAX. Kemudian masukkan buffer string ke parser. Ini akan memunculkan array data sebagai hasilnya. Lihat halaman proyek untuk contoh.
Evan Plaice

75

Jangan pisah pada koma - itu tidak akan berfungsi untuk sebagian besar file CSV, dan pertanyaan ini memiliki terlalu banyak viewy untuk jenis input data penanya untuk berlaku untuk semua orang. Parsing CSV agak menakutkan karena tidak ada standar yang benar-benar resmi, dan banyak penulis teks terbatas tidak mempertimbangkan kasus tepi.

Pertanyaan ini sudah lama, tetapi saya percaya ada solusi yang lebih baik sekarang karena Papa Parse tersedia. Ini adalah perpustakaan yang saya tulis, dengan bantuan dari kontributor, yang mem-parsing teks atau file CSV. Ini satu-satunya perpustakaan JS yang saya tahu mendukung ukuran file gigabytes. Ini juga menangani input yang salah dengan anggun.

File 1 GB diurai dalam 1 menit: Parsing 1 GB file dalam 1 menit

( Pembaruan: Dengan Papa Parse 4, file yang sama hanya membutuhkan waktu sekitar 30 detik di Firefox. Papa Parse 4 sekarang adalah parser CSV yang paling cepat dikenal untuk browser.)

Parsing teks sangat mudah:

var data = Papa.parse(csvString);

Parsing file juga mudah:

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

Mengalirkan file serupa (berikut ini contoh yang mengalirkan file jarak jauh):

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

Jika halaman web Anda terkunci selama parsing, Papa dapat menggunakan pekerja web untuk menjaga situs web Anda reaktif.

Papa dapat mendeteksi pembatas otomatis dan mencocokkan nilai dengan kolom header, jika ada baris header. Itu juga dapat mengubah nilai numerik menjadi tipe angka aktual. Ini secara tepat mem-parsing jeda baris dan kutipan dan situasi aneh lainnya, dan bahkan menangani input yang cacat sekuat mungkin. Saya telah mengambil inspirasi dari perpustakaan yang ada untuk membuat Papa, jadi alat bantu untuk implementasi JS lainnya.


Papa mudah digunakan dan cepat! Terima kasih!
Technotronic

+1 Pekerjaan bagus di Papa Parse. Saya ingin mempelajarinya secara rinci suatu hari nanti untuk melihat bagaimana Anda menangani file besar dan streaming. Saya sangat senang melihat pengembang lain menulis parser berfitur lengkap yang mengambil tempat jquery-csv tinggalkan.
Evan Plaice

3
@ EvanPlaice Terima kasih. Anda mungkin menyukai presentasi yang saya berikan tadi malam di sebuah pertemuan lokal: docs.google.com/presentation/d/…
Matt

1
@ Matt Itu adalah presentasi yang luar biasa yang menjelaskan tentang papa parse dengan cara yang lebih memahami
siva

1
@ Malky.Kid Itu bukan CSV yang valid (mis. Spasi dalam nilai yang tidak dibatasi tidak bagus). Implementasi format CSV MS Excel menyebalkan. Jika Anda masih memiliki akses ke file sumber, harus ada opsi untuk mengaktifkan pembatas kutipan. Setelah Anda melakukannya, data Anda harus bekerja dengan parser csv.
Evan Plaice

10

Saya menggunakan d3.js untuk parsing file csv. Sangat mudah digunakan. Ini dokumennya .

Langkah:

  • npm instal d3-request

Menggunakan Es6;

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

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

Silakan lihat dokumen untuk lebih lanjut.

Pembaruan - permintaan d3 sudah tidak digunakan lagi. Anda bisa menggunakan d3-fetch



3

Berikut adalah fungsi JavaScript yang mem-parsing data CSV, akuntansi untuk koma yang ditemukan di dalam tanda kutip.

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

Contoh penggunaan fungsi untuk mem-parsing file CSV yang terlihat seperti ini:

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

ke dalam array:

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

Inilah cara Anda dapat mengubah data menjadi objek, seperti parser csv D3 (yang merupakan solusi pihak ketiga yang solid):

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

Ini biola yang berfungsi baik dari kode ini .

Nikmati! - Curran


1

Berikut ini cara lain untuk membaca CSV eksternal ke dalam Javascript (menggunakan jQuery).

Ini sedikit lebih panjang, tetapi saya merasa dengan membaca data ke dalam array Anda dapat mengikuti proses dan membuat pemecahan masalah yang mudah.

Mungkin bisa membantu orang lain.

Contoh file data:

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

Dan ini kodenya:

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

Semoga ini bisa membantu seseorang di masa depan!


Halo dari masa depan, jadi saya mencoba jawaban ini dan tidak ada )tanda pada baris 45 jadi saya menambahkannya, tetapi sekarang pada baris 9 memberikan saya kesalahan konsol. Uncaught ReferenceError: $ is not defined at index.html:9Dapatkah Anda membantu dalam hal ini?
Lasagna 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;
    }
}

Saya suka agar regex melakukan sebanyak mungkin. Regex ini memperlakukan semua item sebagai dikutip atau tidak dikutip, diikuti oleh pembatas kolom, atau pembatas baris. Atau akhir dari teks.

Itulah sebabnya kondisi terakhir - tanpanya akan menjadi infinite loop karena polanya dapat cocok dengan bidang panjang nol (benar-benar valid dalam csv). Tapi karena $ adalah pernyataan panjang nol, itu tidak akan berkembang menjadi tidak cocok dan mengakhiri loop.

Dan FYI, saya harus membuat alternatif kedua mengecualikan kutipan yang mengelilingi nilai; Sepertinya itu mengeksekusi sebelum alternatif pertama pada mesin javascript saya dan mempertimbangkan tanda kutip sebagai bagian dari nilai tanda kutip. Saya tidak akan bertanya - baru mulai bekerja.


Sayangnya saya masuk ke loop tak terbatas dengan fungsi ini.
Hauke

@ Hauke ​​- jika Anda bisa memecah data menjadi beberapa kolom dan garis yang masih menghasilkan loop tak terbatas, saya akan menghargai itu - mungkin memberi saya wawasan mengapa saya gagal sebelumnya.
Gerard ONeill

1

Per jawaban yang diterima ,

Saya mendapatkan ini untuk bekerja dengan mengubah 1 ke 0 di sini:

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

diubah menjadi

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

Ini akan menghitung file dengan satu baris kontinu sebagai memiliki allTextLines.length dari 1. Jadi jika loop dimulai pada 1 dan berjalan selama kurang dari 1, ia tidak pernah berjalan. Karenanya kotak peringatan kosong.


0

Jika Anda ingin menyelesaikan ini tanpa menggunakan Ajax , gunakan FileReader()Web API .

Contoh implementasi:

  1. Pilih .csvfile
  2. Lihat output

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>


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

                        }
                      }
                    }

Sementara kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda, dan mungkin menghasilkan lebih banyak suara. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang. Harap edit jawaban Anda untuk menambahkan penjelasan dan berikan indikasi tentang batasan dan asumsi apa yang berlaku. Dari Ulasan
double-beep

0

Sebenarnya Anda bisa menggunakan pustaka ringan yang disebut teks apa saja .

  • instal dependensi
npm i -D any-text
  • gunakan perintah khusus untuk membaca file
var reader = require('any-text');
 
reader.getText(`path-to-file`).then(function (data) {
  console.log(data);
});

atau gunakan 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');
  });
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.