מטפלי קובץ קשורים#
מטפל קובץ קשור מנתב מחדש קלט/פלט באותו אופן שבו סקלר קשור מנתב מחדש קריאות וכתיבות. הדפיסו אליו וה־PRINT שלכם רץ; קראו שורה וה־READLINE שלכם רץ. השימושים הקלאסיים הם הפניית פלט למקום לא־רגיל (אל מחרוזת, לרוחב רשת, דרך מסנן) והטמעת Perl בתוכנית מארחת שזקוקה לטיפול מיוחד ב־STDOUT וב־STDERR.
הממשק גדול יותר מהאחרים אך ברובו אופציונלי: אתם מממשים רק את הפעולות שהמטפל אכן יקבל. התפריט המלא נמצא בעמוד העזר tie; פרק זה בונה מחלקה ומסביר את הווים ואת תזמונם.
מחלקה שלמה#
מטפל לכתיבה בלבד שאוסף למחרוזת את כל מה שמודפס אליו:
use v5.36;
package Collector {
sub TIEHANDLE { my $class = shift; my $buf = ''; return bless \$buf, $class }
sub PRINT { my $self = shift; $$self .= join($, // '', @_); return 1 }
sub PRINTF { my $self = shift; my $fmt = shift; $$self .= sprintf($fmt, @_); return 1 }
sub buffer { my $self = shift; return $$self }
}
tie *OUT, 'Collector';
print OUT "hello ";
print OUT "world\n";
printf OUT "%d items\n", 3;
my $obj = tied *OUT;
print $obj->buffer;
# hello world
# 3 items
העצם הוא הפניית סקלר שעברה blessed ומחזיקה את הטקסט שנצבר. אל מתודת ה־buffer הנוספת מגיעים דרך tied, לא דרך פעולת קלט/פלט כלשהי - זו הדרך הסטנדרטית שבה מחלקת tie חושפת פעולות ללא תחביר של מטפל קובץ.
קישור ה־glob, לא הסקלר#
הארגומנט הראשון אל tie עבור מטפל חייב להיות glob - הוא מתחיל בכוכבית:
כדי לקשור מטפל בעל שם:
tie *OUT, 'Collector'.כדי לקשור מטפל שמוחזק בסקלר
$fh:tie *$fh, 'Collector'. כתיבתtie $fh, ...קושרת את הסקלר$fh, לא את המטפל שבתוכו - טעות נפוצה ומבלבלת.
חוזה המתודות#
TIEHANDLE classname, LISTהבנאי; מחזיר הפניה שעברה blessed מכל סוג. הוא יכול להחזיק כל מצב פנימי שהמטפל זקוק לו.
PRINT this, LISTתומך ב־
printוב־say. הוא מקבל את הרשימה המודפסת. כבדו את$,(מפריד שדות הפלט) בין פריטים ואת$\(מסיים רשומת הפלט) בסוף אם אתם רוצים נאמנות מלאה -printאינו מכניס אותם עבורכם.PRINTF this, format, LISTתומך ב־
printf. הוא מקבל את מחרוזת הפורמט ואת הארגומנטים; העבירו אותם דרךsprintfבעצמכם.WRITE this, scalar, length, offsetתומך ב־
syswrite- הכתיבה הגולמית, מוכוונת ה־buffer, הנבדלת מ־PRINT.READLINE thisתומך ב־
<$fh>וב־readline. בהקשר סקלרי החזירו את השורה הבאה אוundefבסוף הקלט; בהקשר רשימה החזירו את כל השורות הנותרות או רשימה ריקה. המחרוזות המוחזרות צריכות לכלול את מפריד רשומת הקלט$/, בהתאמה למה שמטפל אמיתי נותן לכם.READ this, scalar, length, offset/GETC thisOPEN,CLOSE,EOF,BINMODE,FILENO,SEEK,TELLתומכים במובנים המתאימים כאשר משתמשים בהם על המטפל. מממשים את אלה שהגיוניים עבור המאגר התומך שלכם ומשמיטים את השאר.
DESTROY this/UNTIE thisניקוי אופציונלי, זהה בתפקידו לסוגי ה־tie האחרים. מחלקת מטפל לעיתים קרובות סוגרת כאן את המשאב התומך שלה.
תזמון הקריאה#
print FH @listו־say FH @list→PRINT.sayבנוסף עושה localise ל־$\אל"\n"סביב הקריאה, ולכןPRINTשמכבד את$\מטפל ב־sayללא מקרה מיוחד.printf FH $fmt, @args→PRINTF.syswrite FH, $buf, $len, $off→WRITE.<FH>/readline FH→READLINE, בהקשר הסובב.read/sysread→READ;getc FH→GETC.close FH,eof FH,binmode FH,seek,tell,fileno,open FH, ...→ הוו באותיות רישיות המתאים כאשר הוא מוגדר.
הערה על STDERR: כאשר STDERR קשור, ה־PRINT שלו הוא מה שמנפיק אזהרות והודעות שגיאה. זמן הריצה משבית את ה־tie למשך אותה קריאה, כך שתוכלו לבצע warn מתוך PRINT בלי לעורר רקורסיה אינסופית.
מחלקה מינימלית ברת־קיימא#
אין מתודת חובה יחידה מעבר ל־TIEHANDLE - אתם מממשים את כל הפעולות שהמטפל יקבל. מטפל לפלט בלבד זקוק ל־TIEHANDLE בתוספת PRINT (ובדרך כלל PRINTF). מטפל לקלט בלבד זקוק ל־TIEHANDLE בתוספת READLINE (ואולי GETC / READ). פעולות שהוו שלהן חסר מתות בנקודת השימוש, ולכן הגדירו בדיוק את הקבוצה שהקוראים שלכם מפעילים.
הדרך הקלה: ירושה מ־Tie::StdHandle#
Tie::StdHandle (מסופק בתוך Tie::Handle) קושר מטפל אל מטפל בסיסי אמיתי: ה־OPEN שלו פותח קובץ ממשי וווי הקלט/פלט מעבירים אליו. ירשו ממנו ועקפו רק את הפעולות שאתם רוצים ליירט:
package Doubler {
use Tie::StdHandle;
our @ISA = ('Tie::StdHandle');
sub READLINE {
my $self = shift;
my $line = $self->SUPER::READLINE;
return defined $line ? $line . $line : undef; # echo each line twice
}
}
my $data = "a\nb\n";
tie *DUP, 'Doubler';
tied(*DUP)->OPEN('<', \$data);
print while defined($_ = <DUP>);
# a
# a
# b
# b
READLINE קורא כלפי מעלה אל מחלקת הבסיס עבור השורה הבאה האמיתית, ואז מכפיל אותה; כל פעולה אחרת זורמת דרך Tie::StdHandle ללא שינוי. Tie::Handle (ההורה) הוא הבסיס המופשט שמתעד את הממשק ומספק PRINT/PRINTF ברירת מחדל באמצעות WRITE; Tie::StdHandle הוא הקונקרטי, המוכן לשימוש.
ראו גם#
tie- המובנה ותפריט המתודות המלא של המטפלtied- הדרך היחידה להגיע אל מתודות שאינן קלט/פלט של מחלקת מטפל, כמוbufferלמעלהreadline- העמוד שלו מתעד את חוזה ההחזרה הסקלרי/רשימה ש־READLINEחייב לכבדסקלרים קשורים - סוג ה־tie הפשוט ביותר, חימום טוב לקראת ממשק המטפל
Tie::Handle- מודול מחלקת הבסיס;Tie::StdHandleהוא הגרסה הקונקרטית