Як читати дані з файлу * .CSV за допомогою JavaScript?


196

Мої дані CSV виглядають так:

заголовок1, заголовок2, заголовок3, заголовок4, заголовок5, значення1_1, значення2_1, значення3_1, значення4_1, значення5_1, значення1_2, значення2_2, значення3_2, значення4_2, значення5_2 ....

Як ви читаєте ці дані та перетворюєте на такий масив за допомогою Javascript ?:

[заголовок1: значення1_1, заголовок2: значення2_1, заголовок3: значення3_1, заголовок4: значення4_1, заголовок5: значення5_1], [заголовок1: значення1_2, заголовок2: значення2_2, заголовок3: значення3_2, заголовок4: значення4_2, заголовок5: значення5_2] ....

Я спробував цей код, але не пощастило:

<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-файлі неможливо будь-який код JavaScript знати, де зупиняється один масив (або об’єкт), а інший починається (якщо ви не знаєте заздалегідь, що завжди є рівно п’ять заголовків). Це був надзвичайний нагляд?
Blazemonger

Так, я заздалегідь знаю, що існує саме п’ять полів.
Mahesh Thumar

1
Наступне питання: чи дозволено jQuery у рішенні? Ви використовували тег, але ваш зразок коду - це чистий JavaScript.
Blazemonger

так, jQuery дозволено, тому я включаю його в тег.
Mahesh Thumar

1
Я не думаю, що використання file://...дозволено XMLHttpRequest.
Ноель Ллеварес

Відповіді:


118

ПРИМІТКА. Я придумав це рішення до того, як мені нагадали про всі "особливі випадки", які можуть виникнути у дійсному файлі CSV, як уникнуті цитати. Я залишаю свою відповідь тим, хто хоче чогось швидкого і брудного, але рекомендую відповідь Евана для точності.


Цей код буде працювати, коли у вашому data.txtфайлі є один довгий рядок записів, розділених комами, без нових рядків:

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

Наступний код буде працювати на "справжньому" CSV-файлі з розривами рядків між кожним набором записів:

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
До речі, це передбачає, що файл CSV насправді має кілька рядків - ось що allText.split(/\r\n|\n/)розбивається. Якщо всі ваші дані - це один довгий рядок даних, розділених комами, без нових рядків, це не справжній файл CSV.
Blazemonger

1
Привіт, я використовую цей код: Але виходу немає. Просто відображається пусте попередження. мій файл виглядає так: заголовок1, заголовок2, заголовок3, заголовок4, заголовок5, значення1_1, значення2_1, значення3_1, значення4_1, значення5_1, значення1_2, значення2_2, значення3_2, значення4_2, значення5_2 Обидва csv.html і data.txt знаходяться в одній папці
Mahesh Thumar

Якщо це неправильний файл (або дані), то як має виглядати мій файл ??
Mahesh Thumar

7
Код може не обробляти всі дійсні файли CSV стандартного стандарту IETF і може вийти з ладу, якщо є рядки, в які вбудовані коми, розриви рядків або подвійні лапки. Наприклад, 1, "IETF allows ""quotes"", commas and \nline breaks"що дозволено, оскільки рядок оточений подвійними лапками, а подвійні лапки уникнути.
прототип

1
Я намагався прочитати .csv файл від mac. Мені вдалося отримати цей сценарій для розпізнавання символів нового рядка, коли я змінив перший розділ на цей. var allTextLines = allText.split("\r"); Після цього він спрацював чудово! Дякую!
Джо

207

Не потрібно писати свої власні ...

Бібліотека jQuery-CSV має функцію, яка називається, $.csv.toObjects(csv)яка виконує відображення автоматично.

Примітка. Бібліотека призначена для обробки будь-яких даних CSV, сумісних з RFC 4180 , включаючи всі випадкові випадки, на які не враховуються більшість "простих" рішень.

Як і вже заявлено @Blazemonger, спочатку потрібно додати перерви рядків, щоб дані були дійсними CSV.

Використовуючи такий набір даних:

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

Використовуйте код:

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

Вихід, збережений у "даних", буде:

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

Примітка. Технічно те, що ви написали відображення ключа-значення, недійсний JavaScript. Об'єкти, що містять пари ключ-значення, слід загорнути в дужки.

Якщо ви хочете спробувати це самі, я пропоную вам ознайомитись з демонстрацією основного використання на вкладці "toObjects ()".

Відмова: Я оригінальний автор jQuery-CSV.

Оновлення:

Відредаговано, щоб використовувати набір даних, який надав оп, і включив посилання на демонстраційну версію, де дані можна перевірити на достовірність.

Оновлення2:

Через затвор Google Code. jquery-csv перемістився до GitHub


3
IOW, "toObject" - це чи можна вважати "toJSON", ні? І чи є двокрапка, яка слідує за викликом toObjects (csv), помилковою? IOW, чи не повинно це бути крапкою з комою?
Б. Клей Шеннон

11
CSV - це ім'я файлу?
бульбашка

10
Фантастична бібліотека. FYI, csvпереданий параметр - це рядок csv - читайте файл csv як текст, щоб отримати рядок csv.
callmekatootie

3
@Evan Plaice Як користуватися цією бібліотекою для читання з файлу CSV?
Річа Сінья

1
@RichaSinha Прочитайте файл у вигляді текстового буфера через API файлу HTML5 або AJAX. Потім передайте буфер рядків у аналізатор. Як результат, він виплюне масив даних. Див. Приклади на сторінці проекту.
Еван Плейс

75

Не діліться комами - це не працюватиме для більшості файлів CSV, і це питання має занадто багато переглядів, щоб тип вхідних даних запитувача застосовувався до всіх. Розбір CSV - це дуже страшно, оскільки немає справді офіційного стандарту, і багато розмежованих авторів тексту не вважають крайовими справами.

Це питання давнє, але я вважаю, що зараз краще рішення, коли Papa Parse доступний. Це бібліотека, яку я написав за допомогою дописувачів, що аналізує текст CSV або файли. Це єдина бібліотека JS, про яку я знаю, яка підтримує розмір гігабайт файлів. Він також витончено обробляє неправильно введені дані.

1 Гб файл розібраний за 1 хвилину: Проаналізовано 1 ГБ файл за 1 хвилину

( Оновлення. З Папським Парсером 4, той самий файл зайняв лише близько 30 секунд у Firefox. Papa Parse 4 зараз найшвидший відомий аналізатор CSV для браузера.)

Розбір тексту дуже простий:

var data = Papa.parse(csvString);

Розбір файлів також простий:

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

Потокове передавання файлів схоже (ось приклад, який передає віддалений файл):

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

Якщо ваша веб-сторінка блокується під час розбору, Папа може використовувати веб-працівників, щоб підтримувати ваш веб-сайт реактивним.

Папа може автоматично визначати роздільники і співставляти значення з колонками заголовка, якщо є рядок заголовка. Він також може перетворити числові значення в фактичні типи чисел. Він належним чином аналізує розриви рядків та котирування та інші дивні ситуації та навіть обробляє неправильно введені дані максимально рішуче. Я черпав натхнення з існуючих бібліотек для створення Papa, тому реквізити до інших реалізацій JS.


Тато простий у використанні та швидко! Дякую!
Technotronic

+1 Гарна робота на Papa Parse. Я хотів би десь детально вивчити це, щоб побачити, як ви обробляєте великі файли та потокове передавання. Я дуже радий бачити, як інші розробники пишуть повнофункціональні парсери, які підбирають місце, де jquery-csv залишився.
Еван Плейс

3
@EvanPlaice Дякую Можливо, вам сподобається ця презентація, яку я провела вчора ввечері на місцевій зустрічі: docs.google.com/presentation/d/…
Метт

1
@ Метт Це була дивовижна презентація, яка описує розбір папи більш зрозумілим чином
сива

1
@ Malky.Kid Це невірний CSV (тобто пробіли в неозначеному значенні не є хорошими). Реалізація формату CSV MS Excel відстійна. Якщо ви все ще маєте доступ до вихідного файлу, має бути можливість включити роздільники цитат. Після цього ваші дані повинні працювати з будь-яким аналізатором CSV.
Еван Плейс

10

Я використовую d3.js для розбору CSV-файлу. Дуже простий у використанні. Ось документи .

Кроки:

  • npm встановити d3-запит

Використання Es6;

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

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

Щоб отримати докладнішу інформацію, перегляньте документи .

Оновлення - d3-запит застарілий. ви можете використовувати d3-fetch



3

Ось функція JavaScript, яка аналізує дані CSV, враховуючи коми, знайдені всередині лапок.

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

Приклад використання функції для розбору CSV-файлу, який виглядає приблизно так:

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

в масиви:

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

Ось як можна перетворити дані в об'єкти, наприклад , аналізатор csv D3 (який є надійним стороннім рішенням):

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

Ось робоча загадка цього коду .

Насолоджуйтесь! - Куран


1

Ось ще один спосіб прочитати зовнішній CSV в Javascript (за допомогою jQuery).

Це трохи довше звивання, але я відчуваю, що, читаючи дані в масиви, ви можете точно стежити за процесом і полегшує усунення несправностей.

Може допомогти комусь іншому.

Приклад файлу даних:

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

І ось код:

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

Сподіваюся, це допоможе комусь у майбутньому!


Здрастуйте з майбутнього, тому я спробував цю відповідь, і на ній не було )знаку в рядку 45, тому я додав її, але тепер у рядку 9 це дає мені помилку консолі. Uncaught ReferenceError: $ is not defined at index.html:9Чи можете ви допомогти у цьому?
Лазанья Кіт

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

Мені подобається, щоб регекс робив якомога більше. Цей регулярний вираз розглядає всі елементи як цитовані, так і без котирувань, а потім або роздільник стовпця, або роздільник рядків. Або кінець тексту.

Ось чому ця остання умова - без цього це був би нескінченний цикл, оскільки шаблон може відповідати полі нульової довжини (повністю дійсний у csv). Але оскільки $ - це твердження нульової довжини, воно не перейде до невідповідності і не закінчить цикл.

І FYI, мені довелося зробити другу альтернативу, щоб виключити цитати, що оточують значення; здається, що він виконувався перед першою альтернативою на моєму механізмі javascript і розглядав лапки як частину неоціненого значення. Я не буду просити - я просто працюю.


На жаль, я потрапив у нескінченний цикл з цією функцією.
Hauke

@Hauke ​​- якщо ви зможете розбити дані на пару стовпців і рядків, які все ще створюють нескінченний цикл, я би вдячний - це може дати мені зрозуміти, чому я не працював раніше.
Джерард ONeill

1

Відповідно до прийнятої відповіді ,

Я змусив це працювати, змінивши тут 1 на 0:

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

змінено на

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

Він обчислить файл одним суцільним рядком як такий, який має allTextLines.length 1. Отож, якщо цикл починається з 1 і працює до тих пір, поки він менший за 1, він ніколи не запускається. Звідси порожнє поле сповіщення.


0

Якщо ви хочете вирішити це без використання Ajax , використовуйте FileReader()веб-API .

Приклад реалізації:

  1. Виберіть .csvфайл
  2. Дивіться вихід

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

                        }
                      }
                    }

Хоча цей код може вирішити питання, включаючи пояснення, як і чому це вирішує проблему, справді допоможе покращити якість вашої публікації та, ймовірно, призведе до збільшення кількості голосів. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз задає питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються. З огляду
подвійний звуковий сигнал

0

Насправді ви можете використовувати невелику бібліотеку під назвою будь-який текст .

  • встановити залежності
npm i -D any-text
  • використовувати спеціальну команду для читання файлів
var reader = require('any-text');
 
reader.getText(`path-to-file`).then(function (data) {
  console.log(data);
});

або використовувати async-await:

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');
  });
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.