[英]How to read data From *.CSV file using JavaScript?
我的 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
...
如何使用 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
]
....
我試過這段代碼但沒有運氣::
<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);
document.write(allText);
document.write(txtFile);
</script>
不用自己寫...
jQuery-CSV庫有一個名為$.csv.toObjects(csv)
的函數,它會自動進行映射。
注意:該庫旨在處理任何符合RFC 4180的 CSV 數據,包括大多數“簡單”解決方案忽略的所有令人討厭的邊緣情況。
就像@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:
由於谷歌代碼的關閉。 jquery-csv 已移至 GitHub
注意:在提醒我有效 CSV 文件中可能出現的所有“特殊情況”(如轉義引號)之前,我編寫了此解決方案。 我將把我的答案留給那些想要快速和骯臟的人,但我推薦Evan 的答案以確保准確性。
當您的data.txt
文件是一長串以逗號分隔的條目且沒有換行符時,此代碼將起作用:
數據.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 文件:
數據.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);
}
不要以逗號分隔 - 它不適用於大多數 CSV 文件,而且這個問題對於提問者的輸入數據類型有太多視圖,無法應用於每個人。 解析 CSV 有點嚇人,因為沒有真正的官方標准,而且許多分隔文本作者不考慮邊緣情況。
這個問題很老,但我相信現在有更好的解決方案Papa Parse可用。 這是我在貢獻者的幫助下編寫的一個庫,用於解析 CSV 文本或文件。 它是我所知道的唯一一個支持千兆字節大小的文件的 JS 庫。 它還可以優雅地處理格式錯誤的輸入。
1 分鍾解析 1 GB 文件:
(更新:使用 Papa Parse 4,相同的文件在 Firefox 中只用了大約 30 秒。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 可以使用網絡工作者來保持您的網站反應。
如果存在標題行,Papa 可以自動檢測分隔符並將值與標題列匹配。 它還可以將數值轉換為實際的數字類型。 它適當地解析換行符和引號以及其他奇怪的情況,甚至盡可能穩健地處理格式錯誤的輸入。 我從現有的庫中汲取靈感來制作 Papa,從而成為其他 JS 實現的道具。
這是一個解析 CSV 數據的 JavaScript 函數,其中包含引號內的逗號。
// 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));
以下是如何將數據轉換為對象的方法,例如D3 的 csv 解析器(這是一個可靠的第三方解決方案):
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));
享受! ——柯倫
您可以使用 PapaParse 來提供幫助。 https://www.papaparse.com/
這是一個 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; }
});
如果您想在不使用Ajax的情況下解決此問題,請使用FileReader()
Web API 。
示例實現:
.csv
文件 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>
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 中完全有效)。 但是由於 $ 是一個零長度的斷言,它不會進行到不匹配並結束循環。
僅供參考,我必須將第二個選項排除在值周圍的引號; 似乎它在我的 javascript 引擎上的第一個替代方案之前執行,並將引號視為未引用值的一部分。 我不會問 - 只是讓它工作。
根據接受的答案,
我通過在此處將 1 更改為 0 來實現此功能:
for (var i=1; i<allTextLines.length; i++) {
變成
for (var i=0; i<allTextLines.length; i++) {
它將計算一個具有連續行的文件,因為它的 allTextLines.length 為 1。因此,如果循環從 1 開始並且只要它小於 1 就運行,它永遠不會運行。 因此,空白警報框。
$(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]);
}
}
}
實際上,您可以使用一個名為any-text的輕量級庫。
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');
});
});
這是另一種將外部 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]);
}
})
希望這對將來的人有所幫助!
有點晚了,但我希望它可以幫助某人。
前段時間,我什至遇到了一個問題,即字符串數據在兩者之間包含\n
,而在讀取它用來讀取不同行的文件時。
例如。
"Harry\nPotter","21","Gryffindor"
在讀的時候:
Harry
Potter,21,Gryffindor
我在我的角度項目中使用了一個庫csvtojson來解決這個問題。
您可以使用以下代碼將 CSV 文件作為字符串讀取,然后將該字符串傳遞給 csvtojson 庫,它將為您提供 JSON 列表。
示例代碼:
const csv = require('csvtojson');
if (files && files.length > 0) {
const file: File = files.item(0);
const reader: FileReader = new FileReader();
reader.readAsText(file);
reader.onload = (e) => {
const csvs: string = reader.result as string;
csv({
output: "json",
noheader: false
}).fromString(csvs)
.preFileLine((fileLine, idx) => {
//Convert csv header row to lowercase before parse csv file to json
if (idx === 0) { return fileLine.toLowerCase() }
return fileLine;
})
.then((result) => {
// list of json in result
});
}
}
我使用jquery-csv
來做到這一點。
我提供了兩個例子如下
async function ReadFile(file) { return await file.text() } function removeExtraSpace(stringData) { stringData = stringData.replace(/,( *)/gm, ",") // remove extra space stringData = stringData.replace(/^ *| *$/gm, "") // remove space on the beginning and end. return stringData } function simpleTest() { let data = `Name, Age, msg foo, 25, hello world bar, 18, "!! 🐬 !!" ` data = removeExtraSpace(data) console.log(data) const options = { separator: ",", // default "," . (You may want to Tab "\t" or somethings. delimiter: '"', // default " headers: true // default true } // const myObj = $.csv.toObjects(data, options) const myObj = $.csv.toObjects(data) // If you want to use default options, then you can omit them. console.log(myObj) } window.onload = () => { const inputFile = document.getElementById("uploadFile") inputFile.onchange = () => { const inputValue = inputFile.value if (inputValue === "") { return } const selectedFile = document.getElementById('uploadFile').files[0] const promise = new Promise(resolve => { const fileContent = ReadFile(selectedFile) resolve(fileContent) }) promise.then(fileContent => { // Use promise to wait for the file reading to finish. console.log(fileContent) fileContent = removeExtraSpace(fileContent) const myObj = $.csv.toObjects(fileContent) console.log(myObj) }) } }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/1.0.11/jquery.csv.min.js"></script> <label for="uploadFile">Demo 1</label> <input type="file" id="uploadFile" accept=".csv"/> <button onclick="simpleTest()">Demo 2</button>
使用此函數csvToObjs
,您可以將數據條目從CSV 格式轉換為對象數組。
function csvToObjs(string) { const lines = data.split(/\r\n|\n/); let [headings, ...entries] = lines; headings = headings.split(','); const objs = []; entries.map(entry=>{ obj = entry.split(','); objs.push(Object.fromEntries(headings.map((head, i)=>[head, obj[i]]))); }) return objs; } data = `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` console.log(csvToObjs(data));
這是一個老問題,在 2022 年有很多方法可以實現這一目標。 首先,我認為D3是數據處理的最佳替代方案之一。 它是開源的並且可以免費使用,但它也是模塊化的,所以我們可以只導入fetch 模塊。
這是一個基本的例子。 我們將使用傳統模式,因此我將導入整個D3庫。 現在,讓我們調用d3.csv
function 就完成了。 這個function內部調用了fetch
方法,因此可以打開dataURL、url、文件、blob等。
const fileInput = document.getElementById('csv') const outElement = document.getElementById('out') const previewCSVData = async dataurl => { const d = await d3.csv(dataurl) console.log({ d }) outElement.textContent = d.columns } const readFile = e => { const file = fileInput.files[0] const reader = new FileReader() reader.onload = () => { const dataUrl = reader.result; previewCSVData(dataUrl) } reader.readAsDataURL(file) } fileInput.onchange = readFile
<script type="text/javascript" src="https://unpkg.com/d3@7.6.1/dist/d3.min.js"></script> <div> <p>Select local CSV File:</p> <input id="csv" type="file" accept=".csv"> </div> <pre id="out"><p>File headers will appear here</p></pre>
如果我們不想使用任何庫,而只想使用 pain JavaScrip (Vanilla JS),並且我們設法將文件的文本內容作為data
,並且不想使用d3
,我們可以實現一個簡單的 function這會將data
拆分為text
數組,然后我們將提取第一行並拆分為headers
數組, text
的 rest 將是我們將處理的lines
。 之后,我們 map 每一line
並提取其values
,並從一個數組中創建row
object,該數組是通過將每個header
映射到values[index]
中的對應值而創建的。
我們還要使用一個小技巧array
對象在 JavaScript 也可以有屬性。 是的,所以我們將定義一個屬性rows.headers
並將headers
分配給它。
const data = `heading_1,heading_2,heading_3,heading_4,heading_5 value_1_1,value_2_1,value_3_1,value_4_1,value_5_1 value_1_2,value_2_2,value_3_2,value_4_2,value_5_2 value_1_3,value_2_3,value_3_3,value_4_3,value_5_3` const csvParser = data => { const text = data.split(/\r\n|\n/) const [first, ...lines] = text const headers = first.split(',') const rows = [] rows.headers = headers lines.map(line => { const values = line.split(',') const row = Object.fromEntries(headers.map((header, i) => [header, values[i]])) rows.push(row) }) return rows } const d = csvParser(data) // Accessing to the theaders attribute const headers = d.headers console.log({headers}) console.log({d})
最后,讓我們使用 fetch 和解析 csv 文件來實現一個普通的 JS 文件加載器。
const fetchFile = async dataURL => { return await fetch(dataURL).then(response => response.text()) } const csvParser = data => { const text = data.split(/\r\n|\n/) const [first, ...lines] = text const headers = first.split(',') const rows = [] rows.headers = headers lines.map(line => { const values = line.split(',') const row = Object.fromEntries(headers.map((header, i) => [header, values[i]])) rows.push(row) }) return rows } const fileInput = document.getElementById('csv') const outElement = document.getElementById('out') const previewCSVData = async dataURL => { const data = await fetchFile(dataURL) const d = csvParser(data) console.log({ d }) outElement.textContent = d.headers } const readFile = e => { const file = fileInput.files[0] const reader = new FileReader() reader.onload = () => { const dataURL = reader.result; previewCSVData(dataURL) } reader.readAsDataURL(file) } fileInput.onchange = readFile
<script type="text/javascript" src="https://unpkg.com/d3@7.6.1/dist/d3.min.js"></script> <div> <p>Select local CSV File:</p> <input id="csv" type="file" accept=".csv"> </div> <pre id="out"><p>File contents will appear here</p></pre>
我用這個文件來測試它
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.