קלט/פלט

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 לפתרון נייד בתוך התהליך, או השתמש במודול CPAN Term::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 המקורי.

ראו גם#

  • read - קורא מספר קבוע של תווים או בתים בקריאה אחת, מהר בהרבה מללולא על getc

  • readline - קורא רשומה שלמה (שורה) אחת בכל פעם, נשלט על־ידי $/

  • sysread - קריאה לא־מאוגרת ישירות ממערכת ההפעלה, עוקפת את מחסנית שכבות PerlIO

  • eof - בודק האם ה־getc / readline הבא היה מחזיר undef עבור סוף־קובץ

  • $! - errno מוגדר כאשר getc מחזיר undef בשל שגיאת קריאה