קלט/פלט

tell#

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

tell מדווח היכן הקריאה או הכתיבה הבאה ב־FILEHANDLE תתרחש, נמדדת בבתים מתחילת הקובץ. שלבו אותו עם seek כדי לשמור מיקום עכשיו ולחזור אליו מאוחר יותר. אם FILEHANDLE מושמט, tell מדווח את המיקום של המטפל שממנו נקרא לאחרונה - כולל המטפל המשתמע בתוך לולאות while (<FH>).

תקציר#

tell FILEHANDLE
tell

מה מקבלים בחזרה#

offset של בית שלם אי־שלילי בהצלחה, -1 בשגיאה. הערך מתאים כארגומנט POSITION ל־seek כאשר WHENCE מוגדר ל־0 (seek מוחלט). על pipeים, FIFOים, סוקטים, ולפעמים על הזרמים הסטנדרטיים, למערכת ההפעלה הבסיסית אין מיקום שניתן לחפש בו ו־tell מחזיר -1; $! לא בהכרח מוגדר במקרה זה, אז התייחסו ל־-1 כאות הכישלון הסמכותי.

my $pos = tell $fh;
die "not a seekable handle" if $pos < 0;
# ... read or write ...
seek $fh, $pos, 0;                  # back to where we were

מצב גלובלי שהוא נוגע בו#

  • מטפל קובץ אחרון־שנקרא: צורת tell ללא ארגומנט משתמשת במטפל שממנו נקרא לאחרונה בתחום הנוכחי. כל readline, <FH>, או <> מעדכן את זה. ערבוב tell ללא ארגומנט עם מספר מטפלים פעילים הוא מקור לתוצאות מפתיעות - שמו את המטפל במפורש כשבספק.

  • $! אינו ערוץ שגיאה אמין כאן. בדקו -1 ישירות במקום לבדוק את $! לאחר הקריאה.

בתים, לא תווים#

tell תמיד מחזיר offset של בית, גם כאשר למטפל יש שכבת PerlIO מוכוונת־תווים כגון :encoding(UTF-8) או :utf8. זה מכוון: תרגום של ספירת תווים ל־offset של בית בקידוד ברוחב משתנה היה דורש קריאה מחדש של הקובץ מההתחלה. אותו כלל חל על seek ו־sysseek - כולם מדברים בתים.

תוצאה: על קובץ טקסט UTF-8 בדרך כלל אינכם יכולים להשתמש ב־tell כדי לספור תווים. השתמשו בו רק כדי לסמן מיקום שאתם מתכוונים להזין חזרה לתוך seek.

דוגמאות#

זכירת מיקום, קריאה קדימה, חזרה:

open my $fh, "<", "log.txt" or die $!;
my $mark = tell $fh;                # 0
my $first = <$fh>;                  # read one line
seek $fh, $mark, 0;                 # rewind to the mark
my $again = <$fh>;                  # same line again

רישום ה־offset של סוף־הכותרת כדי שקוד מאוחר יותר יוכל לסרוק מחדש את הגוף ללא פירסור מחדש של הכותרת:

while (my $line = <$fh>) {
    last if $line =~ /^\r?\n\z/;    # blank line ends headers
}
my $body_start = tell $fh;
# ... process body ...
seek $fh, $body_start, 0;           # second pass over the body

הצורה ללא־ארגומנט משתמשת במטפל שממנו נקרא לאחרונה. בתוך לולאת while (<>) אותו מטפל הוא ה־ARGV המשתמע:

while (<>) {
    print "at ", tell, ": $_";      # offset within the current file
}

tell על pipe מחזיר -1 מכיוון ש־pipeים אינם ניתנים לחיפוש:

open my $ph, "-|", "ls" or die $!;
my $pos = tell $ph;                 # -1

מטפלי קובץ בתוך ביטויים מורכבים זקוקים לאותה צורת בלוק כמו עם print - tell $handles[0] היא שגיאת תחביר. השתמשו ב:

my @handles = (\*STDIN, $fh);
my $pos = tell { $handles[1] };

מקרי קצה#

  • מטפל קובץ סגור: מחזיר -1. תחת use warnings נפלטת אזהרה tell() on closed filehandle.

  • צורה ללא־ארגומנט, דבר לא נקרא עדיין: מחזיר -1. ה־״מטפל קובץ אחרון־שנקרא״ משמעותי רק לאחר קריאה ממשית.

  • לאחר sysread / syswrite / sysseek: אל תשתמשו ב־tell על מטפל שטיפלתם בו עם משפחת ה־sys*. הפונקציות האלה עוקפות buffering של PerlIO; tell מדווח את המיקום המאוגר, שיהיה שגוי בכמות תוכן ה־buffer. השתמשו ב־sysseek עם whence של 1 ו־offset של 0 כתשאול מיקום בטוח ל־sys*.

  • זרמים סטנדרטיים: tell STDIN, tell STDOUT, tell STDERR עשויים להחזיר -1 או offset משמעותי בתלות אם הזרם מגובה על ידי קובץ רגיל (הפניית shell) או טרמינל, pipe, או סוקט.

  • אין systell: אין פונקציה נפרדת למיקום עוקף־buffering. הניב הוא:

    my $pos = sysseek $fh, 0, 1;
    
  • מצב בינארי לעומת מצב טקסט בפלטפורמות שאינן Linux: pperl מכוון ל־Linux בלבד, אז ה־offsetים של tell תמיד תואמים לבתי הקובץ הגולמיים. שכבות תרגום CRLF המסבכות את tell ב־Perl של משפחת Windows אינן חלות כאן.

  • מצב append (>>): לאחר open my $fh, ">>", ..., ה־tell $fh ההתחלתי עשוי לדווח 0 עד הכתיבה הראשונה, מכיוון שפלטפורמות מסוימות ממקמות את המטפל בסוף־הקובץ רק בכל כתיבה. אל תסתמכו על המיקום ההתחלתי; כתבו פעם אחת, ואז tell.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • seek - קפיצה ל־offset של בית מוחלט שהוחזר קודם על ידי tell

  • sysseek - תשאול מיקום וקפיצה למטפלים שמשמשים עם sysread / syswrite, עוקף buffering של PerlIO

  • telldir - האנלוג של מטפל ספריות; משולב עם seekdir

  • eof - בדיקת סוף־קובץ במקום מיקום מוחלט

  • open - הפקת מטפל הקובץ מלכתחילה; המצב ושכבות PerlIO קובעים אם המטפל ניתן לחיפוש