Как добавить новую строку в существующий CSV-файл в nodejs json2csv?
Я хочу добавить новую строку в существующий CSV-файл? Если CSV-файл существует, то я не хочу добавлять заголовок столбца и просто хочу добавить новую строку после существующей строки в файле.
Вот код, который я пытаюсь:
var fields = ['total', 'results[0].name.val'];
var fieldNames = ['Total', 'Name'];
var opts1 = {
data: data,
fields: fields,
fieldNames: fieldNames,
newLine: '\r\n'
};
var opts2 = {
newLine: '\r\n',
data: data,
fields: fields,
fieldNames: fieldNames,
hasCSVColumnTitle: false,
};
fs.stat('file.csv', function (err, stat) {
if (err == null) {
console.log('File exists');
var csv = json2csv(opts2);
fs.appendFile('file.csv', csv, function (err) {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
} else if (err.code == 'ENOENT') {
// file does not exist
var csv = json2csv(opts1);
fs.writeFile('file.csv', csv, function (err) {
if (err) throw err;
console.log('file saved');
});
} else {
console.log('Some other error: ', err.code);
}
});
2 ответа
Следующий код будет делать то, что вы просили:
- При первом запуске - напишу заголовки
Каждый прогон после этого - будет добавлять данные в файл CSV.
var fs = require('fs'); var json2csv = require('json2csv'); var newLine= "\r\n"; var fields = ['Total', 'Name']; var appendThis = [ { 'Total': '100', 'Name': 'myName1' }, { 'Total': '200', 'Name': 'myName2' } ]; var toCsv = { data: appendThis, fields: fields, hasCSVColumnTitle: false }; fs.stat('file.csv', function (err, stat) { if (err == null) { console.log('File exists'); //write the actual data and end with newline var csv = json2csv(toCsv) + newLine; fs.appendFile('file.csv', csv, function (err) { if (err) throw err; console.log('The "data to append" was appended to file!'); }); } else { //write the headers and newline console.log('New file, just writing headers'); fields= (fields + newLine); fs.writeFile('file.csv', fields, function (err, stat) { if (err) throw err; console.log('file saved'); }); } });
Кажется, последняя версия json2csv
имеет специальный метод под названием .parse()
для преобразования JSON в совместимую строку CSV. Я старалсяjson2csv.parse()
конвертер, и он работает у меня.
Общая проблема:
Я обнаружил общую проблему в приведенных здесь решениях. Решения не добавляют данные безHEADER
если мы запустим метод несколько раз.
Решение:
Я использовал header
логическая опция, предоставляемая json2csv
чтобы исправить проблему. Если мы проанализируем с{header:false}
вариант мы получим данные в виде строк.
// Rows without headers.
rows = json2csv(data, { header: false });
Ниже приведен код, который работает именно так, как я упоминал выше:
Пример кода:
Ниже приведен пример кода:
const fs = require('fs');
const path = require('path');
const json2csv = require('json2csv').parse;
const write = async (fileName, fields, data) => {
// output file in the same folder
const filename = path.join(__dirname, 'CSV', `${fileName}`);
let rows;
// If file doesn't exist, we will create new file and add rows with headers.
if (!fs.existsSync(filename)) {
rows = json2csv(data, { header: true });
} else {
// Rows without headers.
rows = json2csv(data, { header: false });
}
// Append file function can create new file too.
fs.appendFileSync(filename, rows);
// Always add new line if file already exists.
fs.appendFileSync(filename, "\r\n");
}
Вызов Write
Функция
У нас есть 3 параметра:
fields = ['Name', 'Position', 'Salary'];
data = [{
'Name': 'Test1',
'Position': 'Manager',
'Salary': '$10500'
},
{
'Name': 'Test2',
'Position': 'Tester',
'Salary': '$5500'
}, {
'Name': 'Test3',
'Position': 'Developer',
'Salary': '$5500'
}, {
'Name': 'Test4',
'Position': 'Team Lead',
'Salary': '$7500'
}];
Теперь вызываем функцию write
:
write('test.csv', fields, data);
Каждый раз, когда мы вызываем вышеуказанный метод, он пишет с новой строки. Он записывает заголовки только один раз, если файл не существует.
Используйте функцию csv-write-stream для добавления данных в файл csv.
https://www.npmjs.com/package/csv-write-stream Добавьте эту строку с флагом "a"
writer.pipe (fs.createWriteStream ('out.csv', {flags: 'a'}))
Я внес некоторые изменения в поведение функции, теперь я проверяю с помощью двух методов, есть ли заголовок, если он существует, я игнорирую его и добавляю строки, если нет, я добавляю заголовок, удаляю кавычки из объектов и передаю некоторые awaits, потому что функция была синхронизирована, а ожидание не было, поэтому не имело смысла быть асинхронным, хахаха
Значение CSV, переданное в filename, - это имя папки, которую узел будет искать в корне проекта, чтобы сохранить окончательный документ.
Fiz umas mudanças em como a função se comporta, agora eu valido com 2 métodos se existe cabeçalho, se existir eu ignoro ele e adiciono as rows, se não eu adiciono o cabeçalho, removes as aspas dos objetos e Passenger uns awaits era sync e não tinha nenhum await então não fazia sentido ser async hahaha
O valor CSV passado para o nome do arquivo é o nome da pasta que o nó procurará na raiz do projeto para salvar seu documento final
const fs = require("fs");
const path = require("path");
const json2csv = require("json2csv").parse;
// Constructor method to assist our ReadFileSync
const readFileSync = filePath =>
fs.readFileSync(filePath, { encoding: "utf-8" });
// A helper to search for values in files =D
const findWord = async (text, filePath) => {
const result = await readFileSync(path.join(__dirname, filePath));
return Promise.resolve(RegExp("\\b" + text + "\\b").test(result));
};
const write = async (fileName, fields, data) => {
// output file in the same folder
const filename = path.join(__dirname, "CSV", `${fileName}`);
let rows;
// I check if there is a header with these items
const hasValue = await findWord("Name,Position,Salary", "./CSV/test.csv");
// If there is a header I add the other lines without it if I don't follow the natural flow
if (hasValue) {
rows = json2csv(data, { header: false });
} else if (!fs.existsSync(fields)) {
// If file doesn't exist, we will create new file and add rows with headers.
rows = json2csv(data, { header: true });
} else {
// Rows without headers.
rows = json2csv(data, { header: false });
}
// I deal with the information by removing the quotes
const newRows = rows.replace(/[\\"]/g, "");
// Append file function can create new file too.
await fs.appendFileSync(filename, newRows);
// Always add new line if file already exists.
await fs.appendFileSync(filename, "\r\n");
};
fields = ["Name", "Position", "Salary"];
data = [
{
Name: "Test1",
Position: "Manager",
Salary: "$10500",
},
{
Name: "Test2",
Position: "Tester",
Salary: "$5500",
},
{
Name: "Test3",
Position: "Developer",
Salary: "$5500",
},
{
Name: "Test4",
Position: "Team Lead",
Salary: "$7500",
},
];
write("test.csv", fields, data);
Output:
"Name","Position","Salary"
"Test1","Manager","$10500"
"Test2","Tester","$5500"
"Test3","Developer","$5500"
"Test4","Team Lead","$7500"
Используя json-2-csv:
/**
* this function will create the file if not exists or append the
* data if exists
*/
function exportToCsvFile(headersArray, dataJsonArray, filename) {
converter.json2csvAsync(dataJsonArray, {prependHeader: false}).then(function (csv) {
fs.exists(filename + '.csv', async function (exists) {
if (!exists) {
var newLine = "\r\n";
var headers = ((headersArray ? headersArray : []) + newLine);
exists= await createFileAsync(filename+ '.csv', headers);
}
if (exists) {
fs.appendFile(filename + '.csv', csv, 'utf8', function (err) {
if (err) {
console.log('error csv file either not saved or corrupted file saved.');
} else {
console.log(filename + '.csv file appended successfully!');
}
});
}
});
}).catch(function (err) {
console.log("error while converting from json to csv: " + err);
return false;
});
}
function createFileAsync(filename, content) {
return new Promise(function (resolve, reject) {
fs.writeFile(filename, content, 'utf8', function (err) {
if (err) {
console.log('error '+filename +' file either not saved or corrupted file saved.');
resolve(0);
} else {
console.log(filename + ' file created successfully!');
resolve(1);
}
});
});
}