Модуль чтения CSV-файлов

#javascript

Вопрос:

У меня есть два каталога, в каждом из которых есть 4 набора CSV-файлов. Пример :

 folder a :
       - animal.csv
       - food.csv
       - fruits.csv

folder b :
      - animal.csv
      - food.csv
      - fruits.csv
 

Теперь мне нужно объединить все файлы, такие как папка a animal.csv, в папку b animal.csv и записать их в

 folder c :
   - animal.csv
   - food.csv
   - fruits.csv
 

Это мой набор кода для чтения и записи одного файла

    const folA= `folderA/animal.csv`;
    const folB = `folderB/animal.csv`;
    const final = `folderC`;
    const filename = "animal";
    const fastcsv = require("fast-csv");
    const csv = require("csv-parser");
    const file1 = [];
    const file2 = [];
    
   //Reading folder A
    fs.createReadStream(folA)
      .pipe(csv())
      .on("data", (data) => file1.push(data))
      .on("end", () => {
        //Reading folder B
        fs.createReadStream(folB)
          .pipe(csv())
          .on("data", (data) => file2.push(data))
          .on("end", () => {
            const finalData = file1.concat(file2);
            console.log(finalData);
            fastcsv
              .writeToPath(`${finalFIlePath}/${filename}.csv`, finalData)
              .on("finish", function () {
                console.log("Done");
              });
          });
      });
 

Когда я запускаю это, я получаю объединенный файл animal.csv в папке C. Но мне нужно сделать то же самое, чтобы сохранить файл в папке после запуска.

Ответ №1:

Возможно, вам потребуется создать универсальную функцию, которая принимает имя входного и выходного файлов и объединяет их друг с другом, и вызвать эту функцию 3 раза, так как у вас есть 3 файла для чтения и объединения, в настоящее время вы делаете это для 1 файла.

 const fastcsv = require("fast-csv");
const csv = require("csv-parser");


mergeFiles ('folderA/animal.csv', 'folderB/animal.csv', 'folderC/', 'animal.csv');
mergeFiles ('folderA/food.csv', 'folderB/animal.csv', 'folderC/', 'food.csv');
mergeFiles ('folderA/fruits.csv', 'folderB/animal.csv', 'folderC/', 'fruits.csv');


function mergeFiles (folA, folB, finalFIlePath, filename) {
    //Reading folder A
    const file1 = [];
    const file2 = [];
    fs.createReadStream(folA)
        .pipe(csv())
        .on("data", (data) => file1.push(data))
        .on("end", () => {
            //Reading folder B
            fs.createReadStream(folB)
                .pipe(csv())
                .on("data", (data) => file2.push(data))
                .on("end", () => {
                    const finalData = file1.concat(file2);
                    console.log(finalData);
                    fastcsv
                        .writeToPath(`${finalFIlePath}/${filename}.csv`, finalData)
                        .on("finish", function () {
                            console.log("Done");
                        });
                });
        });
}
 

Комментарии:

1. Я пытался сделать это в одной функции, но я не могу этого достичь, я новичок в этом

2. Я верю, что вам безразличен порядок, в котором он будет написан, обновляя ответ

3. он должен читать оба файла животных только в одно и то же время и записывать, как только животные закончат следующую еду

4. Если он считывает данные из обоих файлов вместе, собранные данные будут тарабарщиной, вам придется читать по одному файлу за раз, чтобы понять смысл окончательных данных.

5. Получил это вместо жесткого кодирования местоположения файлов трехкратного слияния, можем ли мы выполнить итерацию. Bcos в моем случае это будет 10 разных файлов из разных каталогов

Ответ №2:

Вы можете использовать этот фрагмент для объединения нескольких файлов. Примечания в комментариях.

 const fs = require('fs');
const path = require('path');
const { parse, writeToPath } = require('fast-csv');

// The folders which we want to merge their files
const folders = [
    path.resolve('./folder_a'),
    path.resolve('./folder_b'),
];

// The destination folder
const finalFolder = path.resolve('./folder_c');

// Create the destination if it is not there
if (!fs.existsSync(finalFolder)) fs.mkdirSync(finalFolder);

// Function to return a file's contents
const parseFile = async (file, folder) => {
    
    return new Promise((resolve) => {
        
        const contents = [];

        fs.createReadStream(`${folder}/${file}`)
            .pipe(parse())
            .on('data', (data) => {
                contents.push(data);
            })
            .once('end', () => {

                resolve({
                    file,
                    header: contents[0],
                    contents: contents.slice(1),
                });
            });
    });
};

const main = async () => {
    
    const data = {};

    for (const folder of folders) {

        // Get all the filenames the folder contains
        const files = fs.readdirSync(folder);
        
        // Parse the contents of the folder's files
        const contents = await Promise.all(
            files.map((file) => parseFile(file, folder))
        );

        // Keep for each file its name, header and contents
        for (const content of contents) {

            data[content.file] = data[content.file] || { header: content.header };

            data[content.file].contents = (data[content.file].contents || []).concat(content.contents);
        }
    }

    for (const [filename, { header, contents }] of Object.entries(data)) {

        // Wait for each write operation to finish
        await new Promise((resolve) => {

            writeToPath(`${finalFolder}/${filename}`, [header, ...contents]).once('finish', resolve);
        });
    }
};

main();