كيفية قراءة وكتابة ملفات CSV في Node.js باستخدام Node-CSV

اختار المؤلف Society of Women Engineers لتلقي تبرع كجزء من برنامج الكتابة من أجل التبرعات.

مقدمة

A CSV is a plain text file format for storing tabular data. The CSV file uses a comma delimiter to separate values in table cells, and a new line delineates where rows begin and end. Most spreadsheet programs and databases can export and import CSV files. Because CSV is a plain-text file, any programming language can parse and write to a CSV file. Node.js has many modules that can work with CSV files, such as node-csv, fast-csv, and papaparse.

في هذا البرنامج التعليمي، ستستخدم وحدة node-csv لقراءة ملف CSV باستخدام تيارات Node.js، مما يتيح لك قراءة مجموعات بيانات كبيرة دون استهلاك الكثير من الذاكرة. ستقوم بتعديل البرنامج لنقل البيانات المحللة من ملف CSV إلى قاعدة بيانات SQLite. ستقوم أيضًا باسترداد البيانات من قاعدة البيانات، وتحليلها باستخدام node-csv، واستخدام تيارات Node.js لكتابتها إلى ملف CSV بشكل متقطع.

نشّر تطبيقات Node الخاصة بك من GitHub باستخدام منصة التطبيقات DigitalOcean. دع DigitalOcean تركز على توسيع تطبيقك.

المتطلبات المسبقة

لمتابعة هذا البرنامج التعليمي، ستحتاج إلى:

الخطوة 1 — إعداد دليل المشروع

في هذا القسم، ستقوم بإنشاء دليل المشروع وتنزيل الحزم لتطبيقك. ستقوم أيضًا بتنزيل مجموعة بيانات CSV من إحصاءات نيوزيلندا، التي تحتوي على بيانات الهجرة الدولية في نيوزيلندا.

للبدء، قم بإنشاء دليل يسمى csv_demo وانتقل إلى الدليل:

  1. mkdir csv_demo
  2. cd csv_demo

ثم، قم بتهيئة الدليل كمشروع npm باستخدام الأمر npm init:

  1. npm init -y

الخيار -y يخبر npm init بالموافقة على جميع الاستجوابات. ينشئ هذا الأمر package.json بالقيم الافتراضية التي يمكنك تغييرها في أي وقت.

بعد أن تكون الدليل مهيأً كمشروع npm، يمكنك الآن تثبيت التبعيات اللازمة: node-csv و node-sqlite3.

أدخل الأمر التالي لتثبيت node-csv:

  1. npm install csv

يعد وحدة node-csv مجموعة من الوحدات التي تسمح لك بتحليل وكتابة البيانات في ملف CSV. يقوم الأمر بتثبيت جميع الوحدات الأربعة التي تتكون منها حزمة node-csv: csv-generate، csv-parse، csv-stringify، و stream-transform. ستستخدم وحدة csv-parse لتحليل ملف CSV ووحدة csv-stringify لكتابة البيانات إلى ملف CSV.

بعد ذلك، قم بتثبيت وحدة node-sqlite3:

  1. npm install sqlite3

تتيح لك وحدة node-sqlite3 التفاعل مع قاعدة البيانات SQLite في تطبيقك.

بعد تثبيت الحزم في مشروعك، قم بتنزيل ملف CSV لهجرة نيوزيلندا باستخدام الأمر wget:

  1. wget https://www.stats.govt.nz/assets/Uploads/International-migration/International-migration-September-2021-Infoshare-tables/Download-data/international-migration-September-2021-estimated-migration-by-age-and-sex-csv.csv

اسم ملف CSV الذي قمت بتنزيله طويل. لتسهيل العمل معه، قم بإعادة تسمية اسم الملف إلى اسم أقصر باستخدام الأمر mv:

  1. mv international-migration-September-2021-estimated-migration-by-age-and-sex-csv.csv migration_data.csv

اسم ملف CSV الجديد، migration_data.csv، أقصر وأسهل للعمل معه.

باستخدام nano، أو محرر النصوص المفضل لديك، افتح الملف:

  1. nano migration_data.csv

بمجرد فتحه، سترى محتويات مشابهة لهذه:

demo_csv/migration_data.csv
year_month,month_of_release,passenger_type,direction,sex,age,estimate,standard_error,status
2001-01,2020-09,Long-term migrant,Arrivals,Female,0-4 years,344,0,Final
2001-01,2020-09,Long-term migrant,Arrivals,Male,0-4 years,341,0,Final
...

السطر الأول يحتوي على أسماء الأعمدة، وجميع السطور التالية تحتوي على البيانات المقابلة لكل عمود. يفصل كل قطعة بيانات فاصلة. هذا الحرف يُعرف بالفاصل لأنه يفصل الحقول. لست مقيدًا باستخدام الفواصل. تتضمن الفواصل الشائعة الأخرى النقاط والفواصل (:)، والفواصل المنقوطة (;)، والعلامات (\td). يجب عليك معرفة الفاصل المستخدم في الملف لأن معظم الوحدات يتطلبونه لتحليل الملفات.

بعد مراجعة الملف وتحديد الفاصل، اخرج من ملف migration_data.csv باستخدام CTRL+X.

لقد قمت الآن بتثبيت التبعيات اللازمة لمشروعك. في القسم التالي، ستقوم بقراءة ملف CSV.

الخطوة 2 — قراءة ملفات CSV

في هذا القسم، ستستخدم node-csv لقراءة ملف CSV وتسجيل محتواه في وحدة التحكم. ستستخدم طريقة createReadStream() في وحدة fs لقراءة البيانات من ملف CSV وإنشاء تيار قابل للقراءة. بعد ذلك، ستقوم بتوجيه التيار إلى تيار آخر تم إعداده بوحدة csv-parse لتحليل أجزاء البيانات. بمجرد تحليل أجزاء البيانات، يمكنك تسجيلها في وحدة التحكم.

قم بإنشاء وفتح ملف readCSV.js في محرر النصوص المفضل لديك:

  1. nano readCSV.js

في ملفك readCSV.js، استورد وحدتي fs و csv-parse عن طريق إضافة الأسطر التالية:

demo_csv/readCSV.js
const fs = require("fs");
const { parse } = require("csv-parse");

في السطر الأول، قم بتعريف المتغير fs وتعيينه بكائن fs الذي تعيده طريقة require() في Node.js عند استيراد الوحدة.

في السطر الثاني، تقوم بإستخراج الطريقة parse من الكائن الذي يُعيدُه الطريقة require() إلى المتغير parse باستخدام بنية الإفنتاح.

أضف الأسطر التالية لقراءة ملف CSV:

demo_csv/readCSV.js
...
fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    console.log(row);
  })

تقبل الطريقة createReadStream() من الوحدة fs وسيطًا يكون اسم الملف الذي تريد قراءته، والذي هو migration_data.csv هنا. بعد ذلك، تنشئ مجرىً قابلًا للقراءة، الذي يأخذ ملفًا كبيرًا ويقسمه إلى قطع صغيرة. يتيح لك مجرى القراءة فقط قراءة البيانات منه وليس كتابتها.

بعد إنشاء مجرى القراءة، تقوم طريقة pipe() في Node بتوجيه قطع البيانات من مجرى القراءة إلى مجرى آخر. يتم إنشاء المجرى الثاني عند استدعاء طريقة parse() في وحدة csv-parse داخل طريقة pipe(). تقوم وحدة csv-parse بتنفيذ مجرى تحويل (مجرى قابل للقراءة والكتابة)، يأخذ قطعة بيانات ويحوّلها إلى شكل آخر. على سبيل المثال، عندما تتلقى قطعة مثل 2001-01,2020-09,المهاجر على المدى الطويل,وصول,أنثى,0-4 سنوات,344، ستقوم طريقة parse() بتحويلها إلى مصفوفة.

تقوم طريقة parse() بأخذ كائن يقبل الخصائص. يقوم الكائن بتكوين وتوفير مزيد من المعلومات حول البيانات التي ستُحَلل بواسطة الطريقة. يأخذ الكائن الخصائص التالية:

  • يحدد delimiter الحرف الذي يفصل كل حقل في الصف. القيمة , تخبر المحلل بأن الفواصل تفصل بين الحقول.

  • from_line يحدد السطر الذي يجب أن يبدأ المحلل في تحليل الصفوف منه. باستخدام القيمة 2، سيتخطى المحلل السطر 1 ويبدأ من السطر 2. نظرًا لأنك ستقوم بإدراج البيانات في قاعدة البيانات لاحقًا، تساعدك هذه الخاصية في تجنب إدراج أسماء الأعمدة في السطر الأول من قاعدة البيانات.

بعد ذلك، قم بإرفاق حدث تدفق باستخدام طريقة Node.js on(). يسمح حدث التدفق للطريقة باستهلاك جزء من البيانات إذا تم بث حدث معين. يتم تشغيل حدث data عندما تكون البيانات المحولة من طريقة parse() جاهزة للاستهلاك. للوصول إلى البيانات، قم بتمرير استدعاء للرد على طريقة on()، التي تأخذ معلمة تسمى row. تُمثّل معلمة row جزءًا من البيانات تم تحويلها إلى مصفوفة. ضمن الاستدعاء، قم بتسجيل البيانات في وحدة التحكم باستخدام طريقة console.log().

قبل تشغيل الملف، ستقوم بإضافة المزيد من أحداث التيار. تتعامل هذه الأحداث مع الأخطاء وتكتب رسالة نجاح إلى وحدة التحكم عند استهلاك كل البيانات في ملف CSV.

ما زلت في ملف readCSV.js، أضف الكود المظلل التالي:

demo_csv/readCSV.js
...
fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    console.log(row);
  })
  .on("end", function () {
    console.log("finished");
  })
  .on("error", function (error) {
    console.log(error.message);
  });

تتم إرسال حدث end عند قراءة كل البيانات في ملف CSV. عند حدوث ذلك، يتم استدعاء الوظيفة الاستدعائية ويتم تسجيل رسالة تقول أنه تم الانتهاء.

إذا حدث خطأ في أي مكان أثناء قراءة وتحليل بيانات CSV، يتم إرسال حدث error، الذي يستدعي الوظيفة الاستدعائية ويسجل رسالة الخطأ في وحدة التحكم.

يجب أن يبدو ملفك الكامل الآن على النحو التالي:

demo_csv/readCSV.js
const fs = require("fs");
const { parse } = require("csv-parse");

fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    console.log(row);
  })
  .on("end", function () {
    console.log("finished");
  })
  .on("error", function (error) {
    console.log(error.message);
  });

احفظ واخرج من ملف readCSV.js باستخدام CTRL+X.

بعد ذلك، قم بتشغيل الملف باستخدام الأمر node:

  1. node readCSV.js

سيبدو الإخراج مشابهًا لهذا (محرر للتبسيط):

Output
[ '2001-01', '2020-09', 'Long-term migrant', 'Arrivals', 'Female', '0-4 years', '344', '0', 'Final' ] ... [ '2021-09', ... '70', 'Provisional' ] finished

تم تحويل جميع الصفوف في ملف CSV إلى مصفوفات باستخدام تحويل التيار csv-parse. نظرًا لأن تسجيل البيانات يحدث في كل مرة يتم فيها استقبال مقطع من التيار، يبدو البيانات كما لو كانت تُنزل بدلاً من عرضها دفعة واحدة.

في هذه الخطوة، قمت بقراءة البيانات في ملف CSV وتحويلها إلى مصفوفات. في الخطوة التالية، ستقوم بإدراج البيانات من ملف CSV إلى قاعدة البيانات.

الخطوة 3 — إدراج البيانات في قاعدة البيانات

إدراج البيانات من ملف CSV في قاعدة البيانات باستخدام Node.js يمنحك وصولًا إلى مكتبة واسعة من الوحدات التي يمكنك استخدامها لمعالجة أو تنظيف أو تحسين البيانات قبل إدراجها في قاعدة البيانات.

في هذا القسم، ستقوم بإنشاء اتصال مع قاعدة بيانات SQLite باستخدام وحدة node-sqlite3. ستقوم بعد ذلك بإنشاء جدول في قاعدة البيانات، ونسخ ملف readCSV.js، وتعديله لإدراج جميع البيانات المقروءة من ملف CSV في قاعدة البيانات.

أنشئ وافتح ملف db.js في محرر النصوص الخاص بك:

  1. nano db.js

في ملف db.js الخاص بك، أضف الأسطر التالية لاستيراد الوحدات fs و node-sqlite3:

demo_csv/db.js
const fs = require("fs");
const sqlite3 = require("sqlite3").verbose();
const filepath = "./population.db";
...

في السطر الثالث، قم بتعريف مسار قاعدة البيانات SQLite وتخزينه في المتغير filepath. ملف قاعدة البيانات لا يوجد بعد، لكنه سيكون مطلوبًا لـ node-sqlite3 لإنشاء اتصال مع قاعدة البيانات.

في نفس الملف، أضف الأسطر التالية لربط Node.js بقاعدة بيانات SQLite:

demo_csv/db.js
...
function connectToDatabase() {
  if (fs.existsSync(filepath)) {
    return new sqlite3.Database(filepath);
  } else {
    const db = new sqlite3.Database(filepath, (error) => {
      if (error) {
        return console.error(error.message);
      }
      console.log("Connected to the database successfully");
    });
    return db;
  }
}

هنا، تعرّف دالة تُسمى connectToDatabase() لإنشاء اتصال بقاعدة البيانات. داخل الدالة، تقوم باستدعاء طريقة existsSync() من وحدة fs في عبارة if، التي تتحقق مما إذا كان ملف قاعدة البيانات موجودًا في دليل المشروع. إذا كانت شرط if صحيحة، فإنك تنشئ كائن فئة Database() من وحدة node-sqlite3 باستخدام مسار قاعدة البيانات. بمجرد إنشاء الاتصال، تقوم الدالة بإرجاع كائن الاتصال وتنتهي.

ومع ذلك، إذا كانت البيانات المحققة من البيانات الصحيحة (إذا كان ملف قاعدة البيانات غير موجود)، فسيتم تخطي التنفيذ إلى كتلة else. في كتلة else، تقوم بإنشاء كائن فئة Database() بوجود مُعلمتين: مسار ملف قاعدة البيانات ورد استدعاء.

المُعامل الأول هو مسار ملف قاعدة البيانات SQLite، والذي يكون ./population.db. المُعامل الثاني هو رد استدعاء سيُستدعى تلقائيًا عندما يتم بناء الاتصال بقاعدة البيانات بنجاح أو إذا حدث خطأ. يأخذ الرد استدعاء معه مُعامل error، الذي يكون null إذا كان الاتصال ناجحًا. ضمن الرد استدعاء، تُحقق عبارة if مما إذا كان مُعامل الخطأ مُعينًا. إذا كانت القيمة صحيحة، فإن الرد استدعاء يُسجل رسالة خطأ وينتهي. إذا كانت القيمة خاطئة، فإنك تُسجل رسالة نجاح تؤكد أن الاتصال قد تم بنجاح.

حالياً، ينشئ كل من كتل if و else كائن الاتصال. تمرر وظيفة الرد عند استدعاء فئة Database في كتلة else لإنشاء جدول في قاعدة البيانات، ولكن فقط إذا لم يكن ملف قاعدة البيانات موجوداً. إذا كان ملف قاعدة البيانات موجوداً بالفعل، ستقوم الوظيفة بتنفيذ كتلة if، والاتصال بقاعدة البيانات، وإرجاع كائن الاتصال.

لإنشاء جدول إذا لم يكن ملف قاعدة البيانات موجوداً، أضف الكود المظلل:

demo_csv/db.js
const fs = require("fs");
const sqlite3 = require("sqlite3").verbose();
const filepath = "./population.db";

function connectToDatabase() {
  if (fs.existsSync(filepath)) {
    return new sqlite3.Database(filepath);
  } else {
    const db = new sqlite3.Database(filepath, (error) => {
      if (error) {
        return console.error(error.message);
      }
      createTable(db);
      console.log("Connected to the database successfully");
    });
    return db;
  }
}

function createTable(db) {
  db.exec(`
  CREATE TABLE migration
  (
    year_month       VARCHAR(10),
    month_of_release VARCHAR(10),
    passenger_type   VARCHAR(50),
    direction        VARCHAR(20),
    sex              VARCHAR(10),
    age              VARCHAR(50),
    estimate         INT
  )
`);
}

module.exports = connectToDatabase();

الآن يستدعي connectToDatabase() وظيفة createTable()، التي تقبل كائن الاتصال المخزن في متغير db كوسيط.

خارج وظيفة connectToDatabase()، تعرف وظيفة createTable()، التي تقبل كائن الاتصال db كمعلمة. تستدعي الوظيفة exec() على كائن الاتصال db والتي تأخذ عبارة SQL كمعلمة. تقوم العبارة SQL بإنشاء جدول يسمى migration بـ 7 أعمدة. أسماء الأعمدة تتطابق مع العناوين في ملف migration_data.csv.

أخيرًا، تستدعي وظيفة connectToDatabase() وتصدر كائن الاتصال المُرجع من الوظيفة بحيث يمكن إعادة استخدامه في ملفات أخرى.

احفظ واخرج ملف db.js.

بعد تأسيس اتصال قاعدة البيانات، ستقوم الآن بنسخ وتعديل ملف readCSV.js لإدراج الصفوف التي قامت وحدة csv-parse بتحليلها إلى قاعدة البيانات.

انسخ الملف وغيّر اسمه إلى insertData.js باستخدام الأمر التالي:

  1. cp readCSV.js insertData.js

افتح ملف insertData.js في محرر النصوص:

  1. nano insertData.js

أضف الكود المظلل التالي:

demo_csv/insertData.js
const fs = require("fs");
const { parse } = require("csv-parse");
const db = require("./db");

fs.createReadStream("./migration_data.csv")
  .pipe(parse({ delimiter: ",", from_line: 2 }))
  .on("data", function (row) {
    db.serialize(function () {
      db.run(
        `INSERT INTO migration VALUES (?, ?, ? , ?, ?, ?, ?)`,
        [row[0], row[1], row[2], row[3], row[4], row[5], row[6]],
        function (error) {
          if (error) {
            return console.log(error.message);
          }
          console.log(`Inserted a row with the id: ${this.lastID}`);
        }
      );
    });
  });

في السطر الثالث، قم بإستيراد كائن الاتصال من ملف db.js وقم بتخزينه في المتغير db.

في داخل دالة الاستدعاء المرتبطة بحدث data المرفق بوحدة الـ fs، قم بإستدعاء دالة serialize() على كائن الاتصال. تضمن هذه الدالة إتمام عملية تنفيذ الاستعلام الخاص بقاعدة البيانات قبل بدء تنفيذ استعلام آخر، مما يمكن أن يساعد في منع حدوث سباقات قاعدة البيانات حيث يقوم النظام بتشغيل عمليات منافسة بشكل متزامن.

تقوم دالة serialize() بإستدعاء دالة رد الاستدعاء. داخل الدالة الفرعية، قم بإستدعاء دالة run على كائن الاتصال db. الدالة تقبل ثلاثة وسائط:

  • الوسيط الأول هو عبارة SQL سيتم تمريرها وتنفيذها في قاعدة البيانات SQLite. تقبل دالة run() فقط عبارات SQL التي لا تعيد نتائج. عبارة INSERT INTO migration VALUES (?, ..., ? تقوم بإدراج صف في الجدول migration، والعلامات ? هي علامات مكان تم استبدالها في وسيط الدالة الثاني لدالة run().

  • المعامل الثاني هو مصفوفة [row[0], ... row[5], row[6]]. في القسم السابق، تتلقى الطريقة parse() شريحة من البيانات من التيار القابل للقراءة وتحولها إلى مصفوفة. نظرًا لأن البيانات تُستلم كمصفوفة، يجب عليك استخدام فهارس المصفوفة للوصول إلى قيم كل حقل مثل [row[1], ..., row[6]]، إلخ.

  • المعامل الثالث هو استدعاء رد الاتصال الذي يعمل عند إدراج البيانات أو في حالة حدوث خطأ. يقوم رد الاتصال بالتحقق مما إذا كان قد حدث خطأ ويسجل رسالة الخطأ. إذا لم يكن هناك أخطاء، فإن الوظيفة تسجل رسالة نجاح في وحدة التحكم باستخدام طريقة console.log()، مما يُعلمك بأن الصف تم إدراجه مع الهوية.

أخيرًا، احذف أحداث end و error من ملفك. بسبب الطبيعة الغير متزامنة لطرق node-sqlite3، تُنفذ أحداث end و error قبل إدراج البيانات في قاعدة البيانات، لذا لم تعد مطلوبة.

احفظ وأغلق ملفك.

قم بتشغيل ملف insertData.js باستخدام node:

  1. node insertData.js

قد يستغرق الأمر بعض الوقت، ولكن يجب على node إرجاع النتيجة التالية، اعتمادًا على نظامك:

Output
Connected to the database successfully Inserted a row with the id: 1 Inserted a row with the id: 2 ... Inserted a row with the id: 44308 Inserted a row with the id: 44309 Inserted a row with the id: 44310

الرسالة، وخاصةً معرفات، تثبت أن الصف من ملف CSV تم حفظه في قاعدة البيانات.

يمكنك الآن قراءة ملف CSV وإدراج محتواه في قاعدة البيانات. فيما يلي، ستقوم بكتابة ملف CSV.

الخطوة 4 — كتابة ملفات CSV

في هذا القسم، ستقوم بإسترداد البيانات من قاعدة البيانات وكتابتها في ملف CSV باستخدام التدفقات.

قم بإنشاء وفتح writeCSV.js في محرر النصوص الخاص بك:

  1. nano writeCSV.js

في ملفك writeCSV.js، أضف السطور التالية لاستيراد وحدات fs و csv-stringify وكائن اتصال قاعدة البيانات من db.js:

demo_csv/writeCSV.js
const fs = require("fs");
const { stringify } = require("csv-stringify");
const db = require("./db");

تحويل الوحدة csv-stringify يحول البيانات من كائن أو مصفوفة إلى تنسيق نص CSV.

ثم، أضف الأسطر التالية لتعريف متغير يحتوي على اسم ملف CSV الذي ترغب في كتابة البيانات إليه وتيار قابل للكتابة ستكتب البيانات إليه:

demo_csv/writeCSV.js
...
const filename = "saved_from_db.csv";
const writableStream = fs.createWriteStream(filename);

const columns = [
  "year_month",
  "month_of_release",
  "passenger_type",
  "direction",
  "sex",
  "age",
  "estimate",
];

تأخذ طريقة createWriteStream وسيطة تعيين اسم الملف الذي ترغب في كتابة تيار بياناتك إليه، وهو اسم الملف saved_from_db.csv المخزن في المتغير filename.

في السطر الرابع، تعرف متغير columns، الذي يخزن مصفوفة تحتوي على أسماء رؤوس بيانات CSV. سيتم كتابة هذه الرؤوس في السطر الأول من ملف CSV عند بدء كتابة البيانات إلى الملف.

لا تزال في ملفك writeCSV.js، أضف الأسطر التالية لاسترجاع البيانات من قاعدة البيانات وكتابة كل صف في ملف CSV:

demo_csv/writeCSV.js
...
const stringifier = stringify({ header: true, columns: columns });
db.each(`select * from migration`, (error, row) => {
  if (error) {
    return console.log(error.message);
  }
  stringifier.write(row);
});
stringifier.pipe(writableStream);
console.log("Finished writing data");

أولاً، تستدعي طريقة stringify بوجهة نظر كمعامل، والتي تنشئ تيار تحول. يقوم تيار التحويل بتحويل البيانات من كائن إلى نص CSV. الكائن الذي يتم تمريره إلى طريقة stringify() لديه خاصيتان:

  • header تقبل قيمة منطقية وتولّد رأسًا إذا تم تعيين القيمة المنطقية على true.
  • columns تأخذ مصفوفة تحتوي على أسماء الأعمدة التي ستكتب في السطر الأول من ملف CSV إذا تم تعيين الخيار header على true.

ثم، يتم استدعاء الطريقة each() من كائن الاتصال db بمعاملين. يكون المعامل الأول هو عبارة SQL select * from migration التي تسترجع الصفوف واحدا تلو الآخر في قاعدة البيانات. العامل الثاني هو استدعاء رد الاتصال يتم عند كل مرة يتم فيها استرجاع صف من قاعدة البيانات. يأخذ رد الاتصال معه معاملين: كائن error وكائن row يحتوي على البيانات التي تم استرجاعها من صف واحد في قاعدة البيانات. داخل رد الاتصال، يتم التحقق مما إذا كان كائن الخطأ error معينًا في البيانات الموجودة في البيانات في عبارة if. إذا قيمت الشرط على true، يتم تسجيل رسالة خطأ في وحدة التحكم باستخدام الطريقة console.log(). إذا لم يحدث خطأ، يتم استدعاء الطريقة write() على stringifier، التي تكتب البيانات في التيار التحويلي stringifier.

عندما تنتهي الطريقة each() من التكرار، تبدأ الطريقة pipe() على التيار التحويلي stringifier في إرسال البيانات بشكل مجزأ وكتابتها في writableStream. سيقوم التيار القابل للكتابة بحفظ كل مجزأ من البيانات في ملف saved_from_db.csv. بمجرد كتابة جميع البيانات إلى الملف، ستقوم console.log() بتسجيل رسالة نجاح.

الملف الكامل سيبدو الآن كما يلي:

demo_csv/writeCSV.js
const fs = require("fs");
const { stringify } = require("csv-stringify");
const db = require("./db");
const filename = "saved_from_db.csv";
const writableStream = fs.createWriteStream(filename);

const columns = [
  "year_month",
  "month_of_release",
  "passenger_type",
  "direction",
  "sex",
  "age",
  "estimate",
];

const stringifier = stringify({ header: true, columns: columns });
db.each(`select * from migration`, (error, row) => {
  if (error) {
    return console.log(error.message);
  }
  stringifier.write(row);
});
stringifier.pipe(writableStream);
console.log("Finished writing data");

احفظ وأغلق ملفك، ثم قم بتشغيل ملف writeCSV.js في الطرفية:

  1. node writeCSV.js

ستتلقى الناتج التالي:

Output
Finished writing data

للتأكد من أن البيانات قد تمت الكتابة، قم بفحص محتويات الملف باستخدام أمر cat:

  1. cat saved_from_db.csv

القط ستعيد كل الصفوف المكتوبة في الملف (تم تحريرها لأسباب الإيجاز):

Output
year_month,month_of_release,passenger_type,direction,sex,age,estimate 2001-01,2020-09,Long-term migrant,Arrivals,Female,0-4 years,344 2001-01,2020-09,Long-term migrant,Arrivals,Male,0-4 years,341 2001-01,2020-09,Long-term migrant,Arrivals,Female,10-14 years, ...

يمكنك الآن استرداد البيانات من قاعدة البيانات وكتابة كل صف في ملف CSV باستخدام التيارات.

الاستنتاج

في هذه المقالة، قرأت ملف CSV وأدخلت بياناته في قاعدة بيانات باستخدام الوحدات النمطية node-csv و node-sqlite3. ثم قمت باسترداد البيانات من قاعدة البيانات وكتابتها في ملف CSV آخر.

يمكنك الآن قراءة وكتابة ملفات CSV. كخطوة قادمة، يمكنك الآن العمل مع مجموعات بيانات CSV كبيرة باستخدام نفس التنفيذ مع التيارات الكفوءة من حيث استخدام الذاكرة، أو قد تنظر في حزمة مثل event-stream التي تجعل العمل مع التيارات أسهل بكثير.

لمزيد من المعلومات حول node-csv، قم بزيارة وثائقهم مشروع CSV – حزمة CSV لـ Node.js. لمعرفة المزيد عن node-sqlite3، قم بزيارة وثائقهم على Github. لمواصلة تطوير مهاراتك في Node.js، انظر كيفية البرمجة في سلسلة Node.js.

Source:
https://www.digitalocean.com/community/tutorials/how-to-read-and-write-csv-files-in-node-js-using-node-csv