Javascript kullanarak * .CSV dosyasından veri nasıl okunur?


196

CSV verilerim şöyle:

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

Bu verileri nasıl okuyup Javascript kullanarak böyle bir diziye nasıl dönüştürüyorsunuz ?:

[başlık1: değer1_1, başlık2: değer2_1, başlık3: değer3_1, başlık4: değer4_1, başlık5: değer5_1], [başlık1: değer1_2, başlık2: değer2_2, başlık3: değer3_2, başlık4: değer4_2, başlık5: değer5_2] ....

Bu kodu denedim ama şans yok !:

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

CSV dosyanızda satır kesmeleri olmadan, herhangi bir JavaScript kodunun bir dizinin (veya nesnenin) nerede durduğunu ve diğerinin nerede başladığını bilmesi imkansız olacaktır (önceden her zaman tam olarak beş başlık olduğunu bilmiyorsanız). Bu bir kes ve yapıştır gözetimi miydi?
Blazemonger

Evet, önceden Tam Beş Alan olduğunu biliyorum.
Mahesh Thumar

1
Sonraki soru: jQuery'ye çözümde izin veriliyor mu? Etiketi kullandınız, ancak örnek kodunuz saf JavaScript.
Blazemonger

evet, jQuery'ye izin verilir, bu yüzden Etikete ekliyorum.
Mahesh Thumar

1
Kullanımına file://...izin verilmediğini sanmıyorum XMLHttpRequest.
Noel Llevares

Yanıtlar:


118

NOT: Bu çözümü kaçan tırnak işaretleri gibi geçerli bir CSV dosyasında oluşabilecek tüm "özel durumlar" hakkında hatırlatmadan önce uydurdum. Cevabımı hızlı ve kirli bir şey isteyenler için bırakıyorum, ancak Evan'ın cevabını doğruluk için öneriyorum .


Bu kod, data.txtdosyanız satırsonu olmadan virgülle ayrılmış uzun bir giriş dizisi olduğunda çalışır :

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

Aşağıdaki kod, her kayıt kümesi arasında satır aralıkları olan "gerçek" bir CSV dosyasında çalışır:

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
Bu arada, bu, CSV dosyasının aslında birden çok satırı olduğunu varsayar - allText.split(/\r\n|\n/)bölünmeler budur . Tüm verileriniz aslında yeni satır içermeyen virgülle ayrılmış uzun bir veri dizisiyse, gerçek bir CSV dosyası değildir.
Blazemonger

1
Merhaba ben bu kodu kullanıyorum: ama çıktı yok. Sadece boş bir uyarı görüntülenir. dosyam şöyle görünüyor: başlık1, başlık2, başlık3, başlık4, başlık5, değer1_1, değer2_1, değer3_1, değer4_1, değer5_1, değer1_2, değer2_2, değer3_2, değer4_2, değer5_2 Hem csv.html hem de data.txt aynı klasörde
Mahesh Thumar

Bu doğru dosya (veya veri) değilse, o zaman dosyam nasıl görünmeli ??
Mahesh Thumar

7
Kod, geçerli tüm IETF standart CSV dosyalarını işleyemeyebilir ve katıştırılmış virgül, satır kesmeleri veya çift tırnak içeren dizeler varsa başarısız olabilir. Örneğin 1, "IETF allows ""quotes"", commas and \nline breaks", dize çift tırnak içine alındığından ve çift tırnaklardan kaçıldığından izin verilir.
prototip

1
Mac'ten bir .csv dosyası okumaya çalışıyordum. Ben sadece bu ilk bölünmüş değiştirdiğinde newline karakterleri tanımak için bu komut dosyası elde edebildi var allTextLines = allText.split("\r"); Bundan sonra harika çalıştı! Teşekkürler!
Joe

207

Kendi yazmanıza gerek yok ...

JQuery CSV kütüphane adında bir işlevi vardır $.csv.toObjects(csv)otomatik eşleme yapar.

Not: Kütüphane, çoğu 'basit' çözümlerin göz ardı ettiği tüm kötü kenar durumları da dahil olmak üzere RFC 4180 uyumlu tüm CSV verilerini işleyecek şekilde tasarlanmıştır .

@Blazemonger'ın daha önce belirttiği gibi, önce verileri geçerli CSV yapmak için satır sonları eklemeniz gerekir.

Aşağıdaki veri kümesini kullanarak:

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

Kodu kullanın:

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

'Veri'ye kaydedilen çıktı:

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

Not: Teknik olarak, anahtar / değer eşlemesini yazma şekliniz geçersiz JavaScript'tir. Anahtar / değer çiftlerini içeren nesneler parantez içine alınmalıdır.

Kendiniz denemek istiyorsanız, Temel Kullanım Gösterisine bir göz atmanızı öneririm , 'toObjects ()' sekmesi altındaki atmanızı öneririm.

Feragatname: jQuery-CSV'nin asıl yazarıyım.

Güncelleme:

Operasyonun sağladığı veri kümesini kullanmak ve verilerin geçerlilik açısından test edilebileceği demoya bir bağlantı eklemek için düzenlendi.

Update2:

Google Kodunun kapatılması nedeniyle. jquery-csv GitHub'a taşındı


3
IOW, "toObject", "toJSON" olarak düşünülebilir veya düşünülebilir, değil mi? Ve, iki nokta üst üste toObjects (csv) çağrısını izleyen iki nokta üst üste mi? IOW, noktalı virgül olmamalı mı?
B. Clay Shannon

11
CSV bir dosya adı mı?
kabarcık

10
Fantastik kütüphane. FYI, csvgeçirilen parametre bir csv dizesidir - csv dizesini almak için csv dosyasını metin olarak okuyun.
14:14 de callmekatootie

3
@Evan Plaice Bu kütüphane bir csv dosyasından okumak için nasıl kullanılır?
Richa Sinha

1
@RichaSinha HTML5 Dosya API'sı veya AJAX aracılığıyla dosyayı metin arabelleği olarak okuyun. Sonra dize arabelleğini ayrıştırıcıya geçirin. Sonuç olarak bir veri dizisi çıkarır. Örnekler için proje sayfasına bakınız.
Evan Plaice

75

Virgüllere bölünmeyin - çoğu CSV dosyası için çalışmaz ve bu soru, sorucunun tür giriş verilerinin herkese uygulanabilmesi için çok fazla görünüme sahiptir. CSV'yi ayrıştırmak gerçekten korkutucu çünkü gerçekten resmi bir standart yok ve çok sayıda sınırlandırılmış metin yazarı son durumları dikkate almıyor.

Bu soru eski, ama bence Papa Parse artık daha iyi bir çözüm var. CSV metnini veya dosyalarını ayrıştıran katılımcıların yardımıyla yazdığım bir kütüphane. Boyutu gigabayt dosyaları destekleyen bildiğim tek JS kütüphanesi. Ayrıca, hatalı biçimlendirilmiş girdileri de incelikle işler.

1 GB dosya 1 dakikada ayrıştırıldı: 1 GB dosyasını 1 dakikada ayrıştırdı

( Güncelleme: Papa Parse 4 ile aynı dosya Firefox'ta sadece 30 saniye sürdü. Papa Parse 4 şimdi tarayıcı için bilinen en hızlı CSV ayrıştırıcısı .)

Metin ayrıştırmak çok kolaydır:

var data = Papa.parse(csvString);

Dosyaları ayrıştırmak da kolaydır:

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

Akış dosyaları benzerdir (burada uzak bir dosyayı akışa alan bir örnek):

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

Web sayfanız ayrıştırma sırasında kilitlenirse, Papa web sitenizi reaktif tutmak için web çalışanlarını kullanabilir.

Papa, bir başlık satırı varsa sınırlayıcıları otomatik olarak algılayabilir ve değerleri başlık sütunlarıyla eşleştirebilir. Ayrıca sayısal değerleri gerçek sayı türlerine dönüştürebilir. Satır kesmelerini ve tırnak işaretlerini ve diğer garip durumları uygun bir şekilde ayrıştırır ve hatta hatalı biçimlendirilmiş girdileri olabildiğince sağlam bir şekilde işler. Papa yapmak için mevcut kütüphanelerden ilham aldım, bu yüzden diğer JS uygulamalarına destek verdim.


Papa'nın kullanımı kolay ve hızlı! Teşekkürler!
Technotronic

+1 Papa Parse'de iyi iş çıkardın. Büyük dosyaları ve akışları nasıl ele aldığınızı görmek için bir gün ayrıntılı olarak çalışmak istiyorum. Diğer geliştiricilerin jquery-csv'nin kaldığı yerden çıkan tam özellikli ayrıştırıcılar yazdıklarını görmekten çok mutluyum.
Evan Plaice

3
@EvanPlaice Teşekkürler. Dün gece verdiğim bu sunumu yerel bir buluşmada beğenebilirsiniz: docs.google.com/presentation/d/…
Matt

1
@ Matt Bu papa ayrıştırma hakkında daha anlayışla anlatan harika bir sunum oldu
siva

1
@ Malky.Kid Bu geçerli bir CSV değil (örneğin, sınırlandırılmamış bir değerdeki boşluklar iyi değil). MS Excel'in CSV biçimi uygulaması berbat. Kaynak dosyaya hala erişiminiz varsa, teklif sınırlayıcılarını etkinleştirmek için bir seçenek olmalıdır. Bunu yaptıktan sonra, verileriniz herhangi bir csv ayrıştırıcısı ile çalışmalıdır.
Evan Plaice

10

Csv dosyasını ayrıştırmak için d3.js kullanıyorum . Kullanımı çok kolay. İşte dokümanlar .

Adımlar:

  • npm install d3-request

Es6 Kullanımı;

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

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

Daha fazla bilgi için lütfen dokümanlara bakın .

Güncelleme - d3-isteği kullanımdan kaldırıldı. d3-fetch kullanabilirsiniz



3

Burada, tırnak işaretleri içinde bulunan virgülleri hesaba katarak CSV verilerini ayrıştıran bir JavaScript işlevi vardır.

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

Şuna benzeyen bir CSV dosyasını ayrıştırmak için işlevin kullanımına örnek:

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

dizilere:

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

Verileri D3'ün csv ayrıştırıcısı gibi katı bir üçüncü taraf çözümü olan nesnelere nasıl dönüştürebileceğiniz aşağıda açıklanmıştır :

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

İşte bu kodun çalışan bir kemanı .

Zevk almak! - Curran


1

Harici bir CSV'yi Javascript'e okumanın başka bir yolu (jQuery kullanarak).

Biraz daha uzun soluk, ama veriyi dizilere okuyarak süreci tam olarak takip edebileceğinizi ve kolay sorun giderme yapabileceğinizi hissediyorum.

Başka birine yardım edebilir.

Veri dosyası örneği:

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

Ve işte kod:

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

Umarım bu gelecekte birine yardımcı olur!


Gelecekten merhaba, bu yüzden bu cevabı denedim ve )45. satırda bir işaret eksikti , bu yüzden ekledim, ancak şimdi 9. satırda bana bir konsol hatası Uncaught ReferenceError: $ is not defined at index.html:9veriyor Buna yardımcı olabilir misiniz?
Lazanya Kedi

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

Normal ifadenin mümkün olduğunca yapmasını seviyorum. Bu normal ifade, tüm öğeleri tırnak içine alınmış veya tırnaksız olarak değerlendirir, bunu bir sütun sınırlayıcı veya bir satır sınırlayıcı izler. Veya metnin sonu.

Bu yüzden bu son durum - onsuz sonsuz uzunluklu bir alanla eşleşebildiğinden sonsuz bir döngü olurdu (csv'de tamamen geçerlidir). Ancak $ sıfır uzunluklu bir iddia olduğu için eşleşmeyen bir işleme geçmez ve döngüyü sonlandırmaz.

Ve FYI, ikinci alternatif değeri çevreleyen alıntıları hariç tutmak zorunda kaldım; Javascript motorumdaki ilk alternatiften önce yürütülüyor ve tırnak işaretleri tırnaksız değerin bir parçası olarak görülüyor gibi görünüyor. Sormayacağım - sadece işe koyuldum.


Ne yazık ki bu işlevle sonsuz bir döngüye girdim.
Hauke

@Hauke ​​- Verileri hala sonsuz döngüyü üreten birkaç sütun ve çizgiye ayırabilirseniz, bunu takdir ediyorum - daha önce neden başarısız olduğum hakkında bana fikir verebilir.
Gerard ONeill

1

Başına kabul cevap ,

Ben burada 1 0 0 değiştirerek çalışmak için var:

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

olarak değiştirildi

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

Bir sürekli satırlı bir dosyayı allTextLines.length 1 değerine sahip olarak hesaplar. Bu nedenle döngü 1'den başlar ve 1'den az olduğu sürece çalışırsa, asla çalışmaz. Bu nedenle boş uyarı kutusu.


0

Bunu Ajax kullanmadan çözmek istiyorsanız , FileReader()Web API'sını kullanın .

Örnek uygulama:

  1. .csvDosya seç
  2. Çıktıya bakın

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

                        }
                      }
                    }

Bu kod soruyu çözebilir, ancak bunun sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere , yayınınızın kalitesini artırmaya yardımcı olabilir ve muhtemelen daha fazla oyla sonuçlanır. Sadece şimdi soran kişi için değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın. Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğunu belirtin. Şu kaynaktan
double-beep

0

Aslında herhangi bir metin adı verilen hafif bir kütüphane kullanabilirsiniz .

  • yükleme bağımlılıkları
npm i -D any-text
  • dosyaları okumak için özel komutu kullan
var reader = require('any-text');
 
reader.getText(`path-to-file`).then(function (data) {
  console.log(data);
});

veya async-await kullanın:

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');
  });
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.