getc#
קורא את התו הבא הבודד ממטפל קובץ.
getc מחזיר תו אחד של קלט מ־FILEHANDLE, ומקדם את מיקום הקריאה של המטפל בתו זה. אם FILEHANDLE מושמט, getc קורא מ־STDIN. בסוף־הקובץ או בשגיאת קריאה, getc מחזיר undef ו־במקרה השגיאה - מגדיר את $!. היחידה היא תו, לא בית: תחת שכבת PerlIO של :utf8 או :encoding(...) קריאה בודדת צורכת כמה בתים שדרושים להרכיב נקודת קוד מפוענחת אחת.
תקציר#
getc FILEHANDLE
getc
מה מקבלים בחזרה#
מחרוזת באורך תו אחד בהצלחה, או undef בסוף־הקובץ או בשגיאה. הבחן בין השניים על־ידי בדיקת $!:
my $ch = getc $fh;
if (!defined $ch) {
die "read error: $!" if $!;
# otherwise clean EOF
}
מאחר ש־undef קורס עם המחרוזת הריקה "" בהשוואות מחרוזת, תמיד בדוק עם defined, לעולם לא עם length או התאמת מחרוזת.
מצב גלובלי שהוא נוגע בו#
$!- מוגדר כאשרgetcמחזירundefבשל שגיאת קריאה (אינו מוגדר לסוף־קובץ נקי).מטפל הקלט הנוכחי - הצורה ללא־ארגומנטים קוראת מ־
STDIN, לא מהמטפל הנבחר עםselect.selectשולט בפלט ברירת המחדל, לא בקלט ברירת המחדל.מחסנית שכבות PerlIO של המטפל - קובעת אם הסקלר המוחזר הוא בית או תו מפוענח, ואם תרגום CRLF מיושם בדרך פנימה.
דוגמאות#
קריאת תו אחד מ־STDIN:
my $ch = getc;
print "got: $ch\n" if defined $ch;
קריאה ממטפל קובץ מפורש וזיהוי סוף־קובץ:
open my $fh, "<", "input.txt" or die "open: $!";
while (defined(my $ch = getc $fh)) {
print $ch;
}
close $fh;
קריאת תווים, לא בתים, מקובץ UTF-8. כל קריאה מחזירה נקודת קוד מפוענחת אחת גם כאשר זרם הבתים הבסיסי משתמש ברצפים רב־בתיים:
open my $fh, "<:encoding(UTF-8)", "utf8.txt" or die $!;
my $ch = getc $fh; # e.g. "ä" as one character, even though
# it occupies two bytes on disk
צריכת בקשת yes/no מבלי להמתין לשורה שלמה - דורש כיבוי buffering של שורות בטרמינל תחילה (ראה מקרי קצה):
print "continue? [y/n] ";
system "stty", "-icanon", "eol", "\001";
my $key = getc(STDIN);
system "stty", "icanon", "eol", "^@";
print "\n";
exit unless defined $key and lc $key eq "y";
מקרי קצה#
buffering של שורות בטרמינל: ב־
STDINאינטראקטיבי, מנהל ההתקן של הטרמינל אינו מוסר ל־Perl כלום עד שהמשתמש לוחץ Enter, כך ש־getcחוסם עד ששורה מלאה זמינה ואז מחזיר רק את התו הראשון שלה.getcעצמו אינו יכול לעקוף זאת. כדי לקרוא הקשה בודדת, העבר את הטרמינל למצב לא־קנוני (״cbreak״) תחילה - צא ל־stty, השתמש ב־POSIX::termiosדרך מודולPOSIXלפתרון נייד בתוך התהליך, או השתמש במודול CPANTerm::ReadKeyלממשק ידידותי יותר. זכור לשחזר את מצב הטרמינל ביציאה, כולל ממטפלי אותות.בתים מול תווים תחת שכבות I/O: ערך ההחזרה הוא מה שמחסנית השכבות של המטפל מפיקה. מטפל במצב־בתים מניב בית אחד לקריאה; מטפל
:utf8או:encoding(...)מניב תו מפוענח אחד לקריאה, וצורך מהזרם כמה בתים שאותו תו דורש. קלט פגום תחת שכבת פענוח מפעיל את האזהרה או השגיאה הרגילה של השכבה במקום להחזיר זבל בשקט.סוף־קובץ מול שגיאה: שניהם מחזירים
undef.$!מנוקה לפני שנכנסים לקריאה אך מוגדר רק כאשר אירעה שגיאת קריאה ממשית, כך ש־defined $ch or $! and die ...הוא האידיום.מטפל קובץ סגור או לא־פתוח: מחזיר
undefומגדיר את$!ל־Bad file descriptor. תחתuse warningsנפלטת אזהרהgetc() on closed filehandle.יעילות:
getcהוא תו־אחד־בכל־פעם, שחוצה את מחסנית שכבות PerlIO בכל קריאה. לסריקת bulk,read,sysread, אוreadlineמהירים משמעותית; שמור אתgetcלבקשות אינטראקטיביות ולמפענחי פרוטוקול שזקוקים באמת לשליטה תו־בכל־פעם.מטפל ברירת המחדל הוא
STDIN, לאARGV: בניגוד לאופרטור היהלום<>,getcללא ארגומנט אינו עובר על@ARGVאו נופל בחזרה למטפל הקסוםARGV- הוא קורא מ־STDINישירות.קלט טרמינל רחב: קריאת תו מטרמינל במצב raw עדיין מחזירה נקודת קוד אחת רק כאשר שכבת הקלט מפענחת UTF-8. הדבקה המכילה תו רב־בתי תחת מטפל במצב־בתים מופיעה כמספר קריאות
getcנפרדות, אחת לכל בית.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.