seek#
מיקום מחדש של מטפל קובץ עבור קריאות או כתיבות בגישה אקראית.
seek מזיז את מצביע הקריאה/כתיבה של FILEHANDLE ל־offset בתים חדש, ומשקף את קריאת C fseek(3). לאחר seek מוצלח, ה־read, readline או print הבא על המטפל מתחיל מהמיקום החדש. POSITION הוא offset בתים עם סימן; WHENCE בוחר את העוגן שממנו הוא נמדד.
תקציר#
seek FILEHANDLE, POSITION, WHENCE
seek $fh, 0, 0 # rewind to start
seek $fh, 0, 1 # no-op: clear EOF, keep position
seek $fh, -1024, 2 # 1024 bytes before EOF
מה מקבלים בחזרה#
1 בהצלחה, ערך שקר בכישלון (עם $! שנקבע). תמיד יש לבדוק את ערך ההחזרה - seek מעבר לקובץ קצר, על מטפל שאינו ניתן לחיפוש (pipe, socket, TTY), או אחרי שגיאת כתיבה - כולם נכשלים כאן ולא בקריאה הבאה.
seek $fh, $offset, 0
or die "seek to $offset failed: $!";
ערכי WHENCE#
WHENCE הוא מספר שלם עם שלושה ערכים בעלי משמעות. יש להשתמש בקבועים הסימבוליים מ־Fcntl לקריאוּת:
0/SEEK_SET-POSITIONנמדד מתחילת הקובץ.POSITIONחייב להיות אי־שלילי.1/SEEK_CUR-POSITIONמתווסף למיקום הנוכחי. ערכים שליליים נעים אחורה, ערכים חיוביים קדימה.seek $fh, 0, 1הוא האידיום הקנוני ״לא לנוע לשום מקום, אבל לנקות EOF״.2/SEEK_END-POSITIONמתווסף ל־offset של סוף־הקובץ.POSITIONהוא בדרך־כלל אפס או שלילי.
use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END);
seek $fh, 0, SEEK_SET; # rewind
seek $fh, 0, SEEK_END; # go to EOF (e.g. to append)
seek $fh, -$n, SEEK_CUR; # $n bytes back from here
בתים, לא תווים#
גם כאשר למטפל יש שכבה מוכוונת־תווים כגון :encoding(UTF-8), seek, tell, ומשפחת sysseek פועלים על offsets של בתים. seek ל־offset של בתים שנוחת באמצע רצף רב־בתי יפיק שגיאות פענוח או תווי החלפה בקריאה הבאה.
אם נחוץ למקם לפי תווים, יש לקרוא קדימה מגבול בתים ידוע במקום לנסות לתרגם ספירות תווים ל־offsets של בתים. ערכי tell בטוחים להזין בחזרה ל־seek כי הם יוצרו בגבולות בתים ששכבת ה־I/O כבר חצתה נקי.
מצב גלובלי שהוא נוגע בו#
$!- נקבע להודעת שגיאת המערכת בכישלון.ה־buffer של PerlIO של מטפל הקובץ מושלך בהצלחה, ולכן כל נתון שנקרא מראש על־ידי buffering נזרק והקריאה הבאה מושכת בתים טריים מהקובץ הבסיסי.
דגל סוף־הקובץ על
FILEHANDLEמנוקה בהצלחה, גם כאשרPOSITIONו־WHENCEמשאירים את המיקום ללא שינוי.
דוגמאות#
החזרה לתחילת קובץ לפני קריאתו מחדש:
seek $fh, 0, 0 or die "rewind failed: $!";
while (my $line = <$fh>) { ... }
הוספה על־ידי מיקום בסוף־הקובץ, ואז כתיבה. לשימוש הוספה־בלבד, יש להעדיף פתיחה עם >> - צורה זו מיועדת למטפלים שכבר פתוחים לקריאה־כתיבה:
seek $fh, 0, 2 or die $!; # SEEK_END
print $fh "appended line\n";
קריאת רשומה ברוחב קבוע לפי אינדקס, כאשר כל רשומה היא 128 בתים:
my $record = 42;
seek $fh, $record * 128, 0 or die $!;
read $fh, my $buf, 128;
חיקוי של tail -f - ה־seek $fh, 0, 1 מאפס את תנאי ה־EOF כך ש־readline הבא מנסה שוב את הקובץ לנתונים חדשים:
while (1) {
while (my $line = <$fh>) { print $line }
sleep 1;
seek $fh, 0, 1; # clear EOF, keep position
}
שמירת מיקום עם tell, קריאה קדימה, ואז שחזור:
my $mark = tell $fh;
my $peek = <$fh>;
seek $fh, $mark, 0 or die $!; # back to where we were
מקרי קצה#
מטפלים שאינם ניתנים לחיפוש: pipes, sockets,
TTYs, ורוב ההתקנים המיוחדים מחזירים שקר וקובעים$!ל־ESPIPE(Illegal seek). יש לבדוק את ערך ההחזרה; אין להניח שכל מטפל קובץ ניתן לחיפוש.ערבוב קריאות וכתיבות על אותו מטפל על קובץ שנפתח עם
+<או+>דורשseek(אוtell, או flush מפורש) בעת החלפת כיוון. WHENCE של1עםPOSITIONשל0הוא המפריד no-op הרגיל:seek $fh, 0, 1; # allowed to switch read <-> write
Seek מעבר ל־EOF על קובץ שנפתח לכתיבה הוא חוקי ויוצר חור sparse עד
POSITIONבמערכות קבצים שתומכות בחורים; הכתיבה הבאה ממלאת חלק מהחור והבתים שביניהם נקראים בחזרה כ־"\0".משתמשי
sysread/syswrite: אין לערבבseekעםsysreadאוsyswrite.seekפועל על שכבת ה־buffer של PerlIO; משפחת ה־sys ללא־buffering עוקפת אותה, ולכן המיקומים האפקטיביים שלהם נסחפים זה מזה. יש להשתמש ב־sysseekעבור מטפלים שניגשים אליהם דרך משפחת ה־sys.Offsets של תווים דרך אריתמטיקה: כפל ספירת תווים ברוחב קידוד מונח שגוי עבור
UTF-8וקידודים אחרים ברוחב משתנה. יש להשתמש ב־offsets של בתים שמושגים מ־tell, או לקרוא קדימה מגבול ידוע.מטפלי ספרייה:
seekאינו עובד על מטפלי ספרייה. יש להשתמש ב־seekdirעם מיקום מ־telldir.מטפל קובץ סגור: מחזיר ערך שקר וקובע
$!; תחתuse warningsמנופקת אזהרהseek() on closed filehandle.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
tell- קריאת ה־offset הנוכחי של בתים; הערך עובר הלוך־ושוב בבטחה דרךseekעםWHENCE0sysseek- seek ללא buffering עבור מטפלים שניגשים אליהם דרךsysread/syswrite; להשתמש בו במקוםseekבעת עקיפת PerlIOread- קריאה באורך קבוע עם buffering; השותף הטבעי למיקום לפי offset של בתיםreadline- קריאה מוכוונת־שורה;seek $fh, 0, 1לפני ניסיון חוזר הוא האידיום שלtail -feof- בדיקה לסוף־הקובץ;seekמנקה את דגל ה־EOF שקריאה קודמת אולי קבעהFcntl- מקור הקבועיםSEEK_SET,SEEK_CUR,SEEK_END