Filehandles με tie#
Ένα filehandle με tie δρομολογεί εκ νέου το I/O όπως ένα βαθμωτό με tie δρομολογεί εκ νέου τις αναγνώσεις και τις εγγραφές. Εκτυπώστε σε αυτό και τρέχει το δικό σας PRINT· διαβάστε μια γραμμή και τρέχει το δικό σας READLINE. Οι κλασικές χρήσεις είναι η ανακατεύθυνση της εξόδου κάπου ασυνήθιστα (σε μια συμβολοσειρά, μέσα από δίκτυο, μέσα από ένα φίλτρο) και η ενσωμάτωση της Perl σε ένα πρόγραμμα-ξενιστή που χρειάζεται ειδικό χειρισμό των STDOUT και STDERR.
Η διεπαφή είναι μεγαλύτερη από τις άλλες αλλά κατά κύριο λόγο προαιρετική: υλοποιείτε μόνο τις λειτουργίες που θα λάβει στην πραγματικότητα το handle. Το πλήρες μενού βρίσκεται στη σελίδα αναφοράς του tie· αυτό το κεφάλαιο φτιάχνει μια κλάση και εξηγεί τα hooks και τον χρονισμό τους.
Μια πλήρης κλάση#
Ένα handle μόνο για εγγραφή που συγκεντρώνει σε μια συμβολοσειρά οτιδήποτε εκτυπώνεται σε αυτό:
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, όχι μέσω κάποιας λειτουργίας I/O - αυτός είναι ο τυπικός τρόπος με τον οποίο μια κλάση tie εκθέτει λειτουργίες χωρίς σύνταξη filehandle.
Δέσιμο με tie του glob, όχι του βαθμωτού#
Το πρώτο όρισμα στο tie για ένα handle πρέπει να είναι ένα glob - ξεκινά με αστερίσκο:
Για να δέσετε με tie ένα κατονομασμένο handle:
tie *OUT, 'Collector'.Για να δέσετε με tie ένα handle που κρατείται σε ένα βαθμωτό
$fh:tie *$fh, 'Collector'. Το να γράψετεtie $fh, ...δένει το βαθμωτό$fh, όχι το handle μέσα του - ένα συνηθισμένο και μπερδευτικό λάθος.
Το συμβόλαιο των μεθόδων#
TIEHANDLE classname, LISTΟ κατασκευαστής· επιστρέφει μια blessed αναφορά οποιουδήποτε είδους. Μπορεί να κρατά όποια εσωτερική κατάσταση χρειάζεται το handle.
PRINT this, LISTΣτηρίζει τα
printκαιsay. Λαμβάνει την εκτυπωμένη λίστα. Τιμήστε το$,(τον διαχωριστή πεδίων εξόδου) ανάμεσα στα στοιχεία και το$\(τον τερματιστή εγγραφής εξόδου) στο τέλος αν θέλετε πλήρη πιστότητα - τοprintδεν τα εισάγει για εσάς.PRINTF this, format, LISTΣτηρίζει το
printf. Λαμβάνει τη συμβολοσειρά μορφής και τα ορίσματα· περάστε τα εσείς οι ίδιοι μέσα από τοsprintf.WRITE this, scalar, length, offsetΣτηρίζει το
syswrite- την ακατέργαστη, προσανατολισμένη σε ενταμιευτή εγγραφή, διακριτή από τοPRINT.READLINE thisΣτηρίζει τα
<$fh>καιreadline. Σε βαθμωτό περιβάλλον επιστρέψτε την επόμενη γραμμή ήundefστο τέλος της εισόδου· σε περιβάλλον λίστας επιστρέψτε όλες τις υπόλοιπες γραμμές ή μια κενή λίστα. Οι επιστρεφόμενες συμβολοσειρές πρέπει να περιλαμβάνουν τον διαχωριστή εγγραφής εισόδου$/, ώστε να ταιριάζουν με ό,τι σας δίνει ένα πραγματικό handle.READ this, scalar, length, offset/GETC thisOPEN,CLOSE,EOF,BINMODE,FILENO,SEEK,TELLΣτηρίζουν τις αντίστοιχες ενσωματωμένες όταν χρησιμοποιούνται πάνω στο handle. Υλοποιήστε εκείνες που έχουν νόημα για τον υποκείμενο αποθηκευτικό χώρο σας και αφήστε τις υπόλοιπες απ” έξω.
DESTROY this/UNTIE thisΠροαιρετικός καθαρισμός, ταυτόσημος σε ρόλο με τους άλλους τύπους tie. Μια κλάση handle συχνά κλείνει εδώ τον υποκείμενο πόρο της.
Χρονισμός κλήσεων#
print FH @listκαιsay FH @list→PRINT. Τοsayεπιπλέον εντοπίζει τοπικά το$\σε"\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, ...→ το αντίστοιχο hook με κεφαλαία όταν είναι ορισμένο.
Μια σημείωση για το STDERR: όταν το STDERR είναι δεμένο με tie, το PRINT του είναι αυτό που εκδίδει τις προειδοποιήσεις και τα μηνύματα σφαλμάτων. Ο χρόνος εκτέλεσης απενεργοποιεί το tie για τη διάρκεια εκείνης της κλήσης, οπότε μπορείτε να καλέσετε warn μέσα από το PRINT χωρίς να πυροδοτήσετε άπειρη αναδρομή.
Ελάχιστη βιώσιμη κλάση#
Δεν υπάρχει καμία μεμονωμένη υποχρεωτική μέθοδος πέρα από το TIEHANDLE - υλοποιείτε όποιες λειτουργίες θα λάβει το handle. Ένα handle μόνο για έξοδο χρειάζεται το TIEHANDLE συν το PRINT (και συνήθως το PRINTF). Ένα handle μόνο για είσοδο χρειάζεται το TIEHANDLE συν το READLINE (και ίσως το GETC / READ). Οι λειτουργίες των οποίων το hook λείπει πεθαίνουν στο σημείο χρήσης, οπότε ορίστε ακριβώς το σύνολο που χρησιμοποιούν οι καλούντές σας.
Ο εύκολος τρόπος: κληρονομήστε από το Tie::StdHandle#
Το Tie::StdHandle (που συνοδεύει το Tie::Handle) δένει ένα handle πάνω σε ένα πραγματικό υποκείμενο: το OPEN του ανοίγει ένα πραγματικό αρχείο και τα hooks I/O προωθούν σε αυτό. Κληρονομήστε από αυτό και υπερκαλύψτε μόνο τις λειτουργίες που θέλετε να υποκλέψετε:
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- η ενσωματωμένη και το πλήρες μενού μεθόδων handletied- ο μόνος τρόπος να προσεγγίσετε τις μη-I/O μεθόδους μιας κλάσης handle, όπως τοbufferπαραπάνωprintκαιprintf- οι ενσωματωμένες πίσω από ταPRINTκαιPRINTFreadline- η σελίδα του τεκμηριώνει το συμβόλαιο επιστροφής βαθμωτού/λίστας που πρέπει να τιμά τοREADLINEΒαθμωτά με tie - ο απλούστερος τύπος tie, ένα καλό προθέρμασμα για τη διεπαφή handle
Tie::Handle- το άρθρωμα της βασικής κλάσης· τοTie::StdHandleείναι η συγκεκριμένη εκδοχή