הסופר בחר ב־חברת הנדסאיות הנשים כדי לקבל תרומה כחלק מתוכנית כתיבה למענה.
הקדמה
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 להתמקד בהתרחבות היישום שלך.
נדרשים
כדי לעקוב אחרי המדריך הזה, תצטרך:
-
Node.js מותקן בסביבת הפיתוח המקומית או בשרת. עקוב אחרי איך להתקין Node.js וליצור סביבת פיתוח מקומית כדי להתקין את Node.js.
-
SQLite מותקן על הסביבה המקומית או השרת שלך, וניתן להתקין אותו על ידי עקיפת שלב 1 ב- איך להתקין ולהשתמש ב־SQLite על Ubuntu 20.04. ידע על איך להשתמש ב־SQLite עשוי להיות שימושי וניתן ללמוד בשלבים 2-7 של מדריך ההתקנה.
-
ידע בכתיבת תוכנית Node.js. ראה איך לכתוב ולהפעיל את התוכנית הראשונה שלך ב־Node.js.
-
ידע ב־Node.js streams. ראה איך לעבוד עם קבצים באמצעות זרמים ב־Node.js.
שלב 1 — הגדרת ספריית הפרויקט
בסעיף זה, תיצור את ספריית הפרויקט ותוריד חבילות עבור היישום שלך. תוריד גם קובץ נתונים בפורמט CSV מ-סטטיסטיקה ניו זילנד, אשר מכיל נתוני הגירה בינלאומית בניו זילנד.
כדי להתחיל, צור ספרייה בשם csv_demo
ונווט אל הספרייה:
לאחר מכן, אתחל את הספרייה כפרויקט npm באמצעות הפקודה npm init
:
האופציה -y
מודיעה ל-npm init
לענות "כן" לכל העצות. פקודה זו יוצרת קובץ package.json
עם ערכים ברירת מחדל שניתן לשנות בכל עת.
עם הספרייה שאותחלה כפרויקט npm, כעת ניתן להתקין את התלות הדרושות: node-csv
ו־node-sqlite3
.
הזן את הפקודה הבאה כדי להתקין את node-csv
:
המודול node-csv
הוא אוסף של מודולים שמאפשר לך לנתח ולכתוב נתונים לקובץ CSV. הפקודה מתקינה את כל ארבעת המודולים שהם חלק מחבילת node-csv
: csv-generate
, csv-parse
, csv-stringify
, ו־stream-transform
. תשתמש במודול csv-parse
כדי לנתח קובץ CSV ובמודול csv-stringify
כדי לכתוב נתונים לקובץ CSV.
הבא, התקן את המודול node-sqlite3
:
המודול node-sqlite3
מאפשר לאפליקציה שלך להתקשר עם מסד הנתונים SQLite.
לאחר שתתקין את החבילות בפרויקט שלך, הורד את קובץ ה־CSV להעברת ההגירה של ניו זילנד עם פקודת wget
:
קובץ ה־CSV שהורדת נמצא בשם ארוך. כדי להקל על העבודה איתו, שנה את שם הקובץ לשם קצר יותר באמצעות הפקודה mv
:
שם הקובץ החדש, migration_data.csv
, הוא קצר יותר ונוח יותר לעבוד איתו.
באמצעות nano
, או העורך טקסט המועדף עליך, פתח את הקובץ:
פעם שהקובץ נפתח, תראה תוכן דומה לזה:
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 בעורך הטקסט שלך המועדף:
בקובץ readCSV.js שלך, יבא את מודולי fs ו- csv-parse על ידי הוספת השורות הבאות:
בשורה הראשונה, אתה מגדיר את המשתנה fs ואתה משייך לו את האובייקט fs שהשיטה require() של Node.js מחזירה כאשר היא מייבאת את המודול.
בשורה השנייה, אתה מחלץ את השיטה parse
מהאובייקט שמוחזר על ידי השימוש בשיטת require()
אל משתנה parse
באמצעות תחביר ה הרסתי.
הוסף את השורות הבאות כדי לקרוא את קובץ ה-CSV:
השיטה createReadStream()
ממודול ה-fs
מקבלת ארגומנט של שם הקובץ שברצונך לקרוא, שהוא migration_data.csv
כאן. לאחר מכן, היא יוצרת stream שניתן לקרוא, שמפצה קובץ גדול לחתיכות קטנות יותר. קובץ קריא מאפשר לך לקרוא רק נתונים ממנו ולא לכתוב אליו.
לאחר יצירת ה-stream הקריא, שיטת pipe()
של Node מעבירה חתיכות של נתונים מה-stream הקריא ל-parse()
של מודול csv-parse
מופעלת בתוך שיטת pipe()
. מודול csv-parse
מיישם 2001-01,2020-09,הגירה לטווח ארוך,הגעות,נקבה,0-4 שנים,344
, שיטת ה-parse()
תמיר אותה למערך.
שיטת parse()
מקבלת אובייקט שמקבל תכונות. האובייקט מגדיר ומספק מידע נוסף אודות הנתונים שבהם השיטה תפעל. האובייקט מקבל את התכונות הבאות:
-
delimiter
מגדיר את התו שמפריד בין כל שדה בשורה. הערך,
מוסיף לפרסר את המספרים שבין השדות. -
from_line
מגדיר את השורה ממנה יתחיל הפרסר לנתח את השורות. עם הערך2
, הפרסר ידלג על שורה 1 ויתחיל בשורה 2. מכיוון שתכניתך היא להוסיף את הנתונים למסד הנתונים מאוחר יותר, מאפיין זה עוזר לך להימנע מהוספת שמות העמודות בשורה הראשונה של מסד הנתונים.
לאחר מכן, תצרף אירוע זרימה באמצעות השימוש בשיטת on()
של Node.js. אירוע זרימה מאפשר לשיטה לצרוך חתיכת נתונים אם אירוע מסוים מתפרסם. האירוע data
מתקבל כאשר הנתונים שהומרו משיטת parse()
מוכנים להיות צרופים. כדי לגשת לנתונים, אתה מעביר פונקציית חזרה לשיטת on()
, שמקבלת פרמטר בשם row
. הפרמטר row
הוא חתיכת נתונים שהומרה למערך. בתוך הקולבק, אתה מדפיס את הנתונים בקונסול באמצעות השימוש בשיטת console.log()
.
לפני הרצת הקובץ, תוסיף עוד אירועי זרימה. אלה אירועי זרימה מטפלים בשגיאות וכותבים הודעת הצלחה לקונסולה כאשר כל הנתונים בקובץ ה-CSV נצרפו.
עדיין בקובץ ה-readCSV.js
, הוסף את הקוד המודגש הבא:
אירוע ה-end
מתוודע כאשר כל הנתונים בקובץ ה-CSV נקראו. כאשר זה קורה, ה-callback נקרא ומדפיס הודעה שאומרת שהסתיים.
אם אירעה שגיאה במקום כלשהו במהלך קריאת ופירוק הנתונים ב-CSV, יופעל אירוע ה-error
המדאיג, שיקרא ל-callback וירשום את הודעת השגיאה בקונסולה.
הקובץ השלם שלך צריך להיראות כך עכשיו:
שמור וצא מהקובץ שלך readCSV.js
באמצעות CTRL+X
.
לבא לעבודה, הרץ את הקובץ באמצעות פקודת ה-node
:
הפלט יראה דומה לכך (נערך לצורך קצרה):
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
בעורך שלכם:
בקובץ ה-db.js
שלך, הוסיפו את השורות הבאות כדי לייבא את מודולי ה-fs
וה-node-sqlite3
:
בשורה השלישית, אתה מגדיר את הנתיב של בסיס הנתונים SQLite ושומר אותו במשתנה filepath
. קובץ הבסיס הנתונים עדיין לא קיים, אך יהיה צורך בו כדי ש-node-sqlite3
יציב חיבור עם בסיס הנתונים.
באותו הקובץ, הוסף את השורות הבאות כדי להתחבר את Node.js לבסיס נתונים SQLite:
הנה, אתה מגדיר פונקציה בשם connectToDatabase()
כדי להקים חיבור למסד הנתונים. בתוך הפונקציה, אתה מפעיל את שיטת existsSync()
של מודול ה־fs
בתנאי if
, המוודא אם קובץ המסד קיים בתיקיית הפרויקט. אם התנאי if
מבצעת פעולה חיובית, אתה מיצר את מחלקת ה־Database()
של SQLite ממודול ה־node-sqlite3
עם נתיב המסד הנתונים. לאחר הקימות החיבור, הפונקציה מחזירה את אובייקט החיבור ויוצאת.
עם זאת, אם התנאי if
מבצע פעולה שלילית (אם קובץ המסד אינו קיים), הביצוע ידלג לבלוק ה־else
. בבלוק ה־else
, אתה מיצר את מחלקת ה־Database()
עם שני ארגומנטים: נתיב קובץ מסד הנתונים וקולבק.
הארגומנט הראשון הוא נתיב קובץ מסד הנתונים שהוא ./population.db
. הארגומנט השני הוא קולבק שיפעל אוטומטית כאשר החיבור למסד הנתונים הוקם בהצלחה או אם התרחשה שגיאה. הקולבק מקבל אובייקט error
כפרמטר, המהווה null
אם החיבור הוצלח. בתוך הקולבק, התנאי if
בודק אם אובייקט השגיאה הוגדר. אם הוא מבצע פעולה חיובית, הקולבק מדביק הודעת שגיאה וחוזר. אם הוא מבצע פעולה שלילית, אתה מדביק הודעת הצלחה שמאשרת שהחיבור הוקם.
כרגע, בלוקי if
ו־else
מקימים את אובייקט החיבור. אתה מעביר callback בעת קריאה למחלקת Database
בתוך בלוק ה־else
כדי ליצור טבלה בבסיס הנתונים, אך רק אם קובץ הבסיס הנתונים לא קיים. אם קובץ הבסיס הנתונים כבר קיים, הפונקציה תבצע את בלוק ה־if
, תתחבר לבסיס הנתונים, ותחזיר את אובייקט החיבור.
כדי ליצור טבלה אם קובץ הבסיס הנתונים לא קיים, הוסף את הקוד המודגש:
עכשיו הפונקציה connectToDatabase()
קוראת לפונקציית createTable()
, שמקבלת את אובייקט החיבור המאוחסן במשתנה db
כארגומנט.
מחוץ לפונקציה connectToDatabase()
, אתה מגדיר את פונקציית createTable()
, שמקבלת את אובייקט החיבור db
כפרמטר. אתה קורא לשיטת exec()
על אובייקט החיבור db
שמקבלת הצהרת SQL כארגומנט. ההצהרה SQL יוצרת טבלה בשם migration
עם 7 עמודות. שמות העמודות תואמים לכותרות בקובץ migration_data.csv
.
לבסוף, אתה קורא לפונקציית connectToDatabase()
ומייצא את אובייקט החיבור שהוחזר על ידי הפונקציה כך שניתן יהיה להשתמש בו בקבצים אחרים.
שמור וצא מהקובץ db.js
.
עם החיבור לבסיס הנתונים הנקבע, עכשיו תעתיק ותשנה את קובץ ה־readCSV.js
כדי להוסיף את השורות שניתנו להכנסה לבסיס הנתונים על ידי המודול csv-parse
.
העתק ושנה את שם הקובץ ל־insertData.js
עם הפקודה הבאה:
פתח את קובץ insertData.js
בעורך שלך:
הוסף את הקוד המודגש:
בשורה השלישית, יבא את אובייקט החיבור מקובץ db.js
ואחסן אותו במשתנה db
.
בתוך קולבק האירוע data
שמחובר לזרם המודול fs
, תפעיל את השיטה serialize()
על אובייקט החיבור. השיטה מבטיחה שמשפט SQL יסיים בביצוע לפני שמשפט אחר מתחיל לבצע, מה שיכול לעזור למנוע מצבי תחרות בבסיס נתונים שבהם המערכת מריצה פעולות תחרותיות במקביל.
השיטה 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()
, מעדכנת אותך כי שורה הוכנסה יחד עם ה- id.
לבסוף, הסר את אירועי end
ו-error
מהקובץ שלך. עקב האסינכרוניות של השיטות של node-sqlite3
, אירועי end
ו-error
מתבצעים לפני הכנסת הנתונים למסד הנתונים, לכן הם כבר אינם נדרשים.
שמור וצא מהקובץ שלך.
הפעל את קובץ insertData.js
באמצעות node
:
בהתאם למערכת שלך, ייתכן ויקח זמן מה, אך node
אמור להחזיר את הפלט הבא:
OutputConnected 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
בעורך שלך:
בקובץ writeCSV.js
שלך, הוסף את השורות הבאות כדי לייבא את מודולי fs
ו-csv-stringify
, ואת אובייקט החיבור למסד הנתונים מתוך db.js
:
מודול csv-stringify
ממיר נתונים מאובייקט או מערך לתבנית טקסט של CSV.
אז, הוסף את השורות הבאות כדי להגדיר משתנה שמכיל את שם קובץ ה-CSV שבו ברצונך לכתוב נתונים וזרם ניתן לכתיבה שבו תכתוב נתונים:
שיטת createWriteStream
מקבלת ארגומנט של שם הקובץ שברצונך לכתוב אליו את זרם הנתונים שלך, שהוא שם הקובץ saved_from_db.csv
המאוחסן במשתנה filename
.
בשורה הרביעית, אתה מגדיר משתנה columns
, שמאחסן מערך המכיל את שמות כותרות הנתונים של קובץ ה-CSV. כותרות אלו יודפסו בשורה הראשונה של קובץ ה-CSV כאשר אתה מתחיל לכתוב את הנתונים לקובץ.
עדיין בקובץ ה-writeCSV.js
, הוסף את השורות הבאות כדי לאחזר נתונים ממסד הנתונים ולכתוב כל שורה בקובץ ה-CSV:
ראשית, אתה קורא לשיטת 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()
ירשום הודעת הצלחה.
הקובץ השלם יראה כך:
שמור וסגור את הקובץ שלך, ואז הפעל את קובץ ה-writeCSV.js
בטרמינל:
תקבל את הפלט הבא:
OutputFinished writing data
כדי לוודא שהנתונים נכתבו, בדוק את תוכן הקובץ באמצעות הפקודה cat
.
cat
תחזיר את כל השורות שנכתבו בקובץ (נערך לקצרה):
Outputyear_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".