Как добавить новую строку в существующий 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 ответа

Решение

Следующий код будет делать то, что вы просили:

  1. При первом запуске - напишу заголовки
  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);
            }
        });
    });
}
Другие вопросы по тегам