טיפול בקבצים ב-C++

טיפול בקבצים ב-C++

טיפול בקבצים פירושו קריאה וכתיבה לקבצים (כמו .txt .csv וכו') באמצעות מחלקות המסופקות על ידי הספרייה הסטנדרטית C++.

  • תוכניות פועלות ב-RAM כלומר נתונים קיימים רק בזמן שהתוכנית פועלת כאשר תוכנית מסתיימת כל הנתונים ב-RAM אובדים באופן אוטומטי.
  • טיפול בקבצים מאפשר אחסון נתונים בזיכרון משני (כמו HDD או SSD) כך שניתן לשמר אותם לצמיתות וניתן לשמור אותם ולגשת אליהם גם לאחר סיום התוכנית.
  • עבור פעולות קבצים C++ מספק מחלקות זרם קבצים ב- כותרת כמו ofstream ifstream fstream.

פתיחת קובץ

לפני שקוראים או כותבים לקובץ, עלינו קודם כל לפתוח אותו. פתיחת קובץ טוענת את הקובץ הזה ב-RAM. ב-C++ אנו פותחים קובץ על ידי יצירת זרם אליו באמצעות ה- fstream מחלקה המייצגת את זרם הקובץ כלומר זרם עבור קלט ופלט לקובץ.

C++
   fstream     str  (  'filename.ext'       mode  );   

אֵיפֹה

  • str: השם שניתן לזרם
  • שם קובץ: שם הקובץ
  • מצב : מייצג את הדרך בה אנו עומדים לקיים אינטראקציה עם הקובץ.

מצבי פתיחת קבצים

מצב פתיחת קובץ מציין שהקובץ נפתח לקריאה כתיבה או הוספה. להלן הרשימה של כל מצבי הקבצים ב-C++:

מצב תֵאוּר
ios::in קובץ פתוח לקריאה. אם הקובץ לא קיים פעולת הפתיחה נכשלת.
ios::out קובץ פתוח לכתיבה: מאגר הזרם הפנימי תומך בפעולות פלט.
ios::binary הפעולות מבוצעות במצב בינארי ולא בטקסט.
ios::אכל מיקום הפלט מתחיל בסוף הקובץ.
ios::app כל פעולות הפלט מתרחשות בסוף הקובץ המתווסף לתוכן הקיים שלו.
ios::trunk כל תוכן שהיה קיים בקובץ לפני פתיחתו נמחק.

לְדוּגמָה אם ברצוננו לפתוח את הקובץ לקריאה אנו משתמשים במצב הפתיחה הבא:

C++
   fstream     filein  (  'file.txt'       ios  ::  in  );   

באופן דומה אם ברצוננו לפתוח את הקובץ לכתיבה, אנו משתמשים בדברים הבאים:

C++
   fstream     fileout  (  'file.txt'       ios  ::  out  );   

ניתן לשלב מצבים אלה גם באמצעות אופרטור OR (|). לדוגמה, אתה יכול לפתוח את זרם הקבצים במצב קריאה וכתיבה כמתואר:

C++
   fstream     str  (  'file.txt'       ios  ::  in     |     ios  ::  out  );   

אם הקובץ שנפתח במצב כתיבה אינו קיים נוצר קובץ חדש. אבל אם הקובץ שנפתח במצב קריאה לא קיים אז לא נוצר קובץ חדש ויוצא חריג

זרמי קבצים אחרים

fstream אינו זרם הקבצים היחיד שסופק על ידי C++. ישנם שני זרמים מיוחדים נוספים:

  • ifstream : מייצג זרם קובץ קלט. זה שווה ערך לפתיחת fstream ב ios::in מצב.
  • אוסטרים : מייצג את זרם קובץ הפלט. זה שווה ערך לפתיחת fstream ב ios::out מצב.

המצבים לעיל הם מצבי ברירת מחדל עבור זרמים אלה. מצבים אלה לא ניתנים לשינוי אך ניתן לחבר אותם יחד עם מצבים אחרים. כעת לקלט נוכל להשתמש גם ב-ifstream כפי שמוצג:

C++
   ifstream     filein  (  'file.txt'  );   

באופן דומה עבור פלט:

C++
   ofstream     fileout  (  'file.txt'  );   

כתוב נתונים לקובץ

לאחר פתיחת הקובץ במצב כתיבה באמצעות אחד מהם fstream אוֹ אוסטרים אנו יכולים לבצע את פעולת הכתיבה באופן דומה כמו בשימוש ב-cout < < operator.

C++
   #include          using     namespace     std  ;   int     main  ()     {      // Open a file      ofstream     file  (  'GFG.txt'  );          // Write the string to the file      file      < <     'Welcome to GeeksforGeeks.'  ;      return     0  ;   }   
לִכתוֹבGFG.text

קרא נתונים מקובץ

ברגע שהקובץ נפתח במצב קריאה באמצעות fstream או ifstream נוכל לבצע את פעולת הכתיבה בצורה דומה כמו עם cin באמצעות >> מפעיל.

C++
   #include          using     namespace     std  ;   int     main  ()   {      // Open a file in read mode      ifstream     file  (  'GFG.txt'  );      string     s  ;      // Read string from the file      file     >>     s  ;      cout      < <     'Read String: '      < <     s  ;      return     0  ;   }   


תְפוּקָה

 Read String: Welcome  

יש לזה אותה בעיה כמו cin. הקלט נלקח רק עד תו הרווח הראשון. כדי להימנע מכך אנו יכולים להשתמש ב- getline() לתפקד כפי שמוצג:

C++
   #include          using     namespace     std  ;   int     main  ()   {      // Open a file in read mode      ifstream     file  (  'GFG.txt'  );      string     s  ;      // Read string from the file      getline  (  file       s  );      cout      < <     'Read String: '      < <     s  ;      return     0  ;   }   


תְפוּקָה

 Read String: Welcome to GeeksforGeeks.  

סגירת הקובץ

סגירת הקובץ פירושה סגירת הזרם המשויך ושחרור המשאבים שבהם נעשה שימוש. חשוב לסגור את הקובץ לאחר שתסיימו איתו במיוחד בתוכניות הפועלות ארוכות כדי למנוע דליפות זיכרון אובדן נתונים וכו'.

ב-C++ הקבצים נסגרים באמצעות ה- לִסְגוֹר() פונקציית חבר שקיימת בכל זרמי הקבצים.

C++
   #include          using     namespace     std  ;   int     main  ()   {      // Open a file in read mode      ifstream     file  (  'GFG.txt'  );      string     s  ;      // Read string from the file      getline  (  file       s  );      cout      < <     'Read String: '      < <     s  ;      // Close the file      file  .  close  ();      return     0  ;   }   


תְפוּקָה

 Read String: Welcome to GeeksforGeeks.  

שגיאות בטיפול בקבצים

סוגים רבים ושונים של שגיאות יכולים להתרחש בטיפול בקבצים כגון קובץ לא נמצא שהדיסק מלא וכו'. התוכניות שלנו צריכות לצפות לשגיאות נפוצות וצריכות להיות מסוגלות לטפל בהן כראוי. להלן מספר שגיאות נפוצות שעלולות להתרחש במהלך טיפול בקבצים:

פתיחת קובץ נכשלה

יכולים להיות מקרים בהם הקובץ לא נפתח מסיבות שונות כמו שהוא לא קיים או שלתוכנה אין הרשאה לפתוח אותו וכו'. במקרה זה נוכל להשתמש ב- is_open() פונקציית חבר של מחלקות זרם הקבצים כדי לבדוק אם הקובץ נפתח בהצלחה או לא.

C++
   #include          using     namespace     std  ;   int     main  ()     {      fstream     file  (  'nonexistent_file.txt'       ios  ::  in  );      // Check if the file is opened      if     (  !  file  .  is_open  ())     {      cerr      < <     'Error: Unable to open file!'      < <     endl  ;      return     1  ;      }      file  .  close  ();      return     0  ;   }   


תְפוּקָה

 Error: Unable to open file!  

כשל בקריאה/כתיבה של נתונים

שגיאה נפוצה נוספת היא אי קריאה או כתיבה של נתונים מסיבות כמו מצב שגוי וכו'. במקרה זה נוכל לאמת פעולות לאחר כל ניסיון קריאה/כתיבה. לדוגמה קריאה באמצעות getline() יכולה להיות מאומתת כפי שמראה:

C++
   #include          using     namespace     std  ;   int     main  ()     {      fstream     file  (  'GFG.txt'       ios  ::  out  );      if     (  !  file  .  is_open  ())     {      cerr      < <     'Error: Unable to open file!'      < <     endl  ;      return     1  ;      }      string     line  ;          // Checking if getline() read successfully or not      if     (  !  getline  (  file       line  ))      cerr      < <     'Error: Failed to read data'      < <     endl  ;      file  .  close  ();      return     0  ;   }   


תְפוּקָה

 Error: Failed to read data  

שגיאת סוף קובץ (EOF).

ניסיון לקרוא מעבר לסוף הקובץ עלול לגרום לשגיאת EOF. זה יכול לקרות כאשר אינך בודק את סוף הקובץ לפני הקריאה. אנו יכולים לבדוק EOF באמצעות eof() פונקציית חבר.

C++
   #include          using     namespace     std  ;   int     main  ()   {      ifstream     file  (  'GFG.txt'  );      if     (  !  file  .  is_open  ())      {      cerr      < <     'Error: Unable to open file!'      < <     endl  ;      return     1  ;      }      string     line  ;      while     (  getline  (  file       line  ))      cout      < <     line      < <     endl  ;      // Check for eof      if     (  file  .  eof  ())      cout      < <     'Reached end of file.'      < <     endl  ;      else      cerr      < <     'Error: File reading failed!'      < <     endl  ;      file  .  close  ();      return     0  ;   }   


תְפוּקָה

 Reached end of file.  

שימו לב שגם אימתנו את פעולת הקריאה לפני בדיקת EOF as getline() רק יחזור nullptr גם אם הקריאה נכשלת מסיבה כלשהי.

טיפול בקבצים בינאריים

ב-C++ אנחנו יכולים גם להתמודד קבצים בינאריים המאחסנים נתונים בפורמט גולמי. כדי לקרוא ולכתוב נתונים בינאריים יש להשתמש ב- ios::binary דגל בעת יצירה/פתיחת קובץ בינארי.

כתוב לקובץ בינארי

כדי לכתוב נתונים לקובץ בינארי עלינו קודם כל לפתוח או ליצור את הקובץ בו ios::binary מצב.

C++
   #include         #include         #include          using     namespace     std  ;   int     main  ()   {      string     str     =     'Welcome to GeeksForGeeks'  ;      // Open a binary file for writing      ofstream     file  (  'fileBin.bin'       ios  ::  binary  );      // Check if the file is open      if     (  !  file  )      {      cerr      < <     'Error opening the file for writing.'  ;      return     1  ;      }      // Write the length of the string (size) to file first      size_t     strLength     =     str  .  length  ();      file  .  write  (  reinterpret_cast   <  const     char     *>  (  &  strLength  )     sizeof  (  strLength  ));      // Write the string to the binary file      file  .  write  (  str  .  c_str  ()     strLength  );      // Close the file      file  .  close  ();      return     0  ;   }   


תְפוּקָה

כתובבינאריקובץ בינארי

קריאה מקובץ בינארי

בדיוק כפי שאנו פותחים קובץ במצב בינארי כדי לכתוב נתונים כדי לקרוא נתונים מקובץ בינארי, עלינו לפתוח את הקובץ במצב קריאה באמצעות ios::in .

תַחבִּיר:

C++
   fstream     fileInstance  (  'fileName.bin'       ios  ::  in  |     ios  ::  binary  );   
C++
   #include         #include         #include          using     namespace     std  ;   int     main  ()   {      string     str  ;      // Open the binary file for reading      fstream     file  (  'fileBin.bin'       ios  ::  in     |     ios  ::  binary  );      // Check if the file is open      if     (  !  file  )      {      cerr      < <     'Error opening the file for reading.'  ;      return     1  ;      }      // Read the length of the string (size) from the file      size_t     strLength  ;      file  .  read  (  reinterpret_cast   <  char     *>  (  &  strLength  )     sizeof  (  strLength  ));      // Allocate memory for the string and read the data      char     *  buffer     =     new     char  [  strLength     +     1  ];     // +1 for the null-terminator      file  .  read  (  buffer       strLength  );      // Null-terminate the string      buffer  [  strLength  ]     =     ''  ;      // Convert the buffer to a string      str     =     buffer  ;      // Print file data      cout      < <     'File Data: '      < <     str  ;      delete  []     buffer  ;      file  .  close  ();      return     0  ;   }   


תְפוּקָה

 File Data: Welcome to GeeksForGeeks  

פעולות קובץ אחרות

אנחנו יכולים גם לבצע פעולות נוספות כדי לתפעל קובץ מתוכנית C++ שלנו. חלק מפעולות הקבצים הנפוצות הן:

  • תוכנית C++ למחיקת קובץ
  • הוסף מחרוזת בקובץ קיים
  • העתק קובץ אחד לקובץ אחר
צור חידון