פרק 6: טיפול בקבצים

[הקודם : פונקציות והוראות][חזרה לתוכן העניינים][הבא : מודולים]

6.1 הכוונת קלט\פלט

אחת הדרכים הקלות לטפל בקבצים, זה להזין אותם לתוכנית דרך הקלט\פלט הסטנדרטי. התוכנית תקרא את הקלט כאילו המשתמש כתב אותו, בעזרת האופרטור <>, ותוציא את הפלט בעזרת print רגיל, שינותב לקובץ אחר. דוגמא להרצת תוכנית כזו:

./myprog.pl <inFile >outFile

התוכנית תקבל את הקלט מתוך הקובץ inFile, ותוציא את הפלט לקובץ outFile. והיופי בזה, שהתוכנית בכלל לא יודע שהיא עושה את זה. מבחינתה, היא מקבלת הקלדות מהמשתמש, ומוציאה לו על המסך מידע.
אתה יכול לקחת את תוכנית הדוגמא שבסוף הפרק, להוריד את כל הוראות פתיחת וסגירת הקבצים, ופשוט לחתוך את המילים "InFile" ו-"OutFile". ואם נקרא לתוכנית LinkProcess.pl, אזי אפשר להריץ:

./LinkProcess.pl  < urls.txt  > urls.html

6.2 פתיחת קובץ

הכר את טיפוס הנתונים הרביעי של פרל: קובץ (File Handler). לטיפוס זה אין שום סימן לפניו, ובאופן מסורתי המשתנים נכתבים עם אותיות גדולות. כמו כן, סוג משתנה זה אינו דורש הגדרה, אלא אפשר פשוט להתחיל להשתמש בו, כאילו אין strict.
לפתיחת קובץ משתמשים בפקודת open. (מפתיע, אך אמיתי) אפשר לפתוח קובץ לקריאה ולכתיבה. ככה:

open(FH, ">", "wwwest.txt");

הפקודה הזאת פותחת את הקובץ wwwest.txt לכתיבה. אם הקובץ לא קיים, הוא נוצר.
בד"כ מוסיפים לפקודת open גם פקודת die:

open(FH, ">", "wwwest.txt") or die "Cann’t open wwwest.txt!\n";

פקודת die היא ההתראה (Exception) של פרל. בניגוד לפקודת exit (שגם קיימת) שפשוט מפסיקה את הרצת התוכנית,die מוציאה הודעת שגיאה מסודרת, וסוגרת את התוכנית. אפשר לתפוס את סגירת התוכנית, ולהמשיך אותה בכל זאת, אבל זה סיפור אחר.
בכל מקרה, הפקודה שלמעלה מנסה לפתוח\ליצור את הקובץ לכתיבה. אם היא מצליחה, היא מחזירה אמת, ואין צורך להתקדם לפקודה הבאה. אם היא לא מצליחה, היא מחזירה שקר, ואז פקודת die פועלת ומפסיקה את ההרצה.
פתיחת קובץ לקריאה:

open(FH, "<", "wwwest.txt") or die "Cann’t open wwwest.txt!\n";

פתיחת הקובץ להוספה (Append):

open(FH, ">>", "wwwest.txt") or die "Cann’t open wwwest.txt!\n";

6.3 אופרטור <>

הזכרתי את האופרטור הזה בעבר. מה שהוא עושה, זה לקרוא מקובץ שורה. ככה:

$line = <FH>;

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

while (<>) { 
    chomp; 
    next if (m/^#/); 
    if (m/\\\s*$/) { 
        s/\\\s*$/ /; 
        $_=$_.<>; 
        redo; 
    } 
    print; 
    print "\n"; 
}

פקודת ה-while מפעילה את אופרטור ה-<>, שקורא שורה מתוך הקלט הסטנדרטי. מה ש-<> מחזיר זה תמיד אמת (כיוון שזה מחרוזת הכוללת בין השאר את סימן סוף השורה) אלא אם נגמר הקובץ, ואז זה שקר, מה שמפסיק את הרצת הלולאה. השורה שנקראה נכנסת למשתנה $_.
שורה שניה - עושה chomp ל-$_.
שורה שלישית - בודקת האם הקלט מתחיל בסימן '#'. אם כן - זוהי שורת הערה והולכים לשורה הבאה.
שורה רביעית - בודקים האם הקלט מסתיים בסימן '\'. (זה ביטוי רגולרי. האם המחרוזת מכילה '\', שאחריו אפס או יותר רווחים לבנים, שאחריהם סוף המחרוזת) אם כן, אזי צריך לחבר את השורה עם השורה הבאה. מוחקים את סימן ה-'\', קוראים את השורה הבאה, מחברים את השורות, וקופצים לתחילת הלולאה. (שים לב, זה redo. האופרטור <> שבתוך פקודת ה-while לא מופעל)
ולבסוף, מדפיסים את $_ וסוף ושורה.
תריץ את הקוד הזה, ותנסה להכניס ידנית שורות שמתחילות ב-#, שורות שמסתיימות ב-\, וסתם שורות, ותראה מה קורה. לסיום, לחץ Ctrl+Z, ואנטר.
אם תריץ את האופרטור <> בהקשר רשימה, אז הוא יקרא את כל השורות, ולא רק אחת.

my @lines; 
@lines=<>;

אחרי זה, כל שורות הקלט יהיו בתוך המערך @lines.

6.4 כתיבה לקובץ

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

open(FH, ">", "tmp.txt") or die "AHHHHH!\n"; 
print FH "The time is: " , scalar(localtime()), "\n";

שים לב שאין פסיק בין FH לבין המחרוזת הראשונה. ככה זה. (ואם תשים פסיק, זו תהיה טעות. פקודת ה-print תנסה להדפיס את מחזיק הקובץ. דווקא חוסר הפסיק אומר לו שפה יש מחזיק קובץ, ולא משהו להדפסה)

6.5 סגירת קובץ

בצורה מפתיעה ביותר, בשביל לסגור קובץ משתמשים בפקודת close.

close(FH);

6.6 תוכנית דוגמא

#!/usr/bin/perl -w 
use strict; 
open(InFile, "<", "urls.txt") or die "Error IN!\n"; 
open(OutFile, ">", "urls.html") or die "Error OUT\n"; 
print OutFile "<HTML><HEAD><TITLE>"; 
print OutFile "Semuel's Link Page"; 
print OutFile "</TITLE></HEAD><BODY>"; 
while(<InFile>){ 
    chomp; 
    my $line=$_; 
    if ($line=~m/^http/i) { 
        print OutFile "<A HREF= $line > $line </A><br>\n"; 
    } else { 
        print OutFile "$line <br>\n"; 
    } 
} 
print OutFile"</BODY></HTML>"; 
close(InFile); 
close(OutFile);

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

[הקודם : פונקציות והוראות][חזרה לתוכן העניינים][הבא : מודולים]

נכתב ע"י שמואל פומברג, כל הזכויות שמורות © ראה פרק 1.5 לתנאי רשיון