如何在 nodejs json2csv 中的现有 csv 文件中追加新行?

How to append new row in exist csv file in nodejs json2csv?

我想在现有的 csv 文件中添加新行?如果 csv 文件存在,那么我不想添加列 header,只想在文件中存在的行之后添加新行。

这是我正在尝试的代码:

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

以下代码将执行您的要求:

  1. 第一次运行时-会写headers
  2. 之后的每个 运行 - 都会将 json 数据附加到 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,
  header: 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) {
      if (err) throw err;
      console.log('file saved');
    });
  }
});

使用 csv-write-stream 函数将数据追加到 csv 文件中。

https://www.npmjs.com/package/csv-write-stream 添加这一行,标记 "a"

writer.pipe(fs.createWriteStream('out.csv', {标志: 'a'}))

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

似乎,最新版本的 json2csv 有一个名为 .parse() 的专用方法,可以将 JSON 转换为 CSV 兼容字符串。我尝试了 json2csv.parse() 转换器,它对我有用。

常见问题:

我在此处给出的解决方案中发现了一个常见问题。如果我们多次 运行 该方法,则解决方案不会在没有 HEADER 的情况下附加数据。

解决方案:

我使用 json2csv 提供的 header 布尔选项来解决这个问题。如果我们使用 {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': '500'
    },
    {
        'Name': 'Test2',
        'Position': 'Tester',
        'Salary': '00'
    }, {
        'Name': 'Test3',
        'Position': 'Developer',
        'Salary': '00'
    }, {
        'Name': 'Test4',
        'Position': 'Team Lead',
        'Salary': '00'
    }];

现在调用函数write:

write('test.csv', fields, data);

每次我们调用上面的方法时,它都会从一个新行开始写入。如果文件不存在,它只写一次 headers。

I made some changes in how the function behaves, now I validate with 2 methods if there is a header, if it exists I ignore it and add the rows, if not I add the header, remove the quotation marks from the objects and pass some awaits, because the function it was sync and there was no await so it didn't make sense to be async hahaha

传递给 filename 的 CSV 值是节点将在项目根目录中查找以保存最终文档的文件夹的名称

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, removi as aspas dos objetos e passe uns awaits, porque a função era sync e não tinha nenhum await então não fazia sentido ser async hahaha

为文件名传递的 CSV 值是节点将在项目根目录中查找以保存其最终文档的文件夹的名称

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: "500",
  },
  {
    Name: "Test2",
    Position: "Tester",
    Salary: "00",
  },
  {
    Name: "Test3",
    Position: "Developer",
    Salary: "00",
  },
  {
    Name: "Test4",
    Position: "Team Lead",
    Salary: "00",
  },
];

write("test.csv", fields, data);


Output:
"Name","Position","Salary"
"Test1","Manager","500"
"Test2","Tester","00"
"Test3","Developer","00"
"Test4","Team Lead","00"