seek#
Επανατοποθετεί ένα filehandle για αναγνώσεις ή εγγραφές τυχαίας πρόσβασης.
Η seek μετακινεί τον δείκτη ανάγνωσης/εγγραφής του FILEHANDLE σε νέο offset bytes, αντικατοπτρίζοντας την κλήση C fseek(3). Μετά από επιτυχημένη seek, η επόμενη read, readline ή print επί του handle ξεκινά από τη νέα θέση. Το POSITION είναι προσημασμένο offset bytes· το 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 σε επιτυχία, ψευδής τιμή σε αποτυχία (με το $! τεθειμένο). Ελέγχετε πάντοτε την τιμή επιστροφής - η μετάβαση πέρα από κοντό αρχείο, σε μη-seekable handle (σωλήνας, υποδοχή, 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
Bytes, όχι χαρακτήρες#
Ακόμη και όταν το handle έχει στρώμα προσανατολισμένο σε χαρακτήρες όπως :encoding(UTF-8), οι seek, tell και η οικογένεια της sysseek λειτουργούν επί offsets bytes. Μια seek σε offset bytes που προσγειώνεται στη μέση πολυβυτικής ακολουθίας θα παραγάγει σφάλματα αποκωδικοποίησης ή χαρακτήρες αντικατάστασης στην επόμενη ανάγνωση.
Αν χρειάζεται να τοποθετηθείτε κατά χαρακτήρες, διαβάστε προς τα εμπρός από γνωστό όριο bytes αντί να προσπαθήσετε να μεταφράσετε καταμετρήσεις χαρακτήρων σε offsets bytes. Οι τιμές της tell είναι ασφαλές να τροφοδοτηθούν πίσω στη seek επειδή παράχθηκαν σε όρια bytes που το στρώμα I/O είχε ήδη διασχίσει καθαρά.
Καθολική κατάσταση που επηρεάζει#
$!- τίθεται στο μήνυμα σφάλματος συστήματος σε αποτυχία.Ο ενταμιευτής PerlIO του filehandle απορρίπτεται σε επιτυχία, οπότε όποια δεδομένα έχουν προαναγνωσθεί από την ενταμίευση χάνονται και η επόμενη ανάγνωση τραβά φρέσκα bytes από το υποκείμενο αρχείο.
Η σημαία τέλους αρχείου επί του
FILEHANDLEκαθαρίζεται σε επιτυχία, ακόμη και όταν ταPOSITIONκαιWHENCEαφήνουν τη θέση αμετάβλητη.
Παραδείγματα#
Επαναφορά στην αρχή αρχείου πριν την επανανάγνωσή του:
seek $fh, 0, 0 or die "rewind failed: $!";
while (my $line = <$fh>) { ... }
Προσθήκη με τοποθέτηση στο τέλος αρχείου, και μετά εγγραφή. Για χρήση μόνο προσθήκης, προτιμήστε άνοιγμα με >> - αυτή η μορφή είναι για handles ήδη ανοιγμένα για ανάγνωση-εγγραφή:
seek $fh, 0, 2 or die $!; # SEEK_END
print $fh "appended line\n";
Ανάγνωση εγγραφής σταθερού πλάτους κατά δείκτη, όπου κάθε εγγραφή είναι 128 bytes:
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
Οριακές περιπτώσεις#
Μη-seekable handles: σωλήνες, υποδοχές,
TTYs και οι περισσότερες ειδικές συσκευές επιστρέφουν ψευδές και θέτουν το$!σεESPIPE(Illegal seek). Ελέγξτε την τιμή επιστροφής· μη θεωρείτε δεδομένο ότι κάθε filehandle είναι seekable.Ανάμειξη αναγνώσεων και εγγραφών στο ίδιο handle σε αρχείο ανοιγμένο με
+<ή+>απαιτεί μιαseek(ήtell, ή ρητή εκκένωση) κατά την αλλαγή κατεύθυνσης. Ένα WHENCE1μεPOSITION0είναι ο συνηθισμένος no-op διαχωριστής:seek $fh, 0, 1; # allowed to switch read <-> write
Μετάβαση πέρα από το EOF σε αρχείο ανοιγμένο για εγγραφή είναι νόμιμη και δημιουργεί αραιή τρύπα έως το
POSITIONσε filesystems που υποστηρίζουν τρύπες· η επόμενη εγγραφή γεμίζει μέρος της τρύπας και τα bytes ενδιάμεσα διαβάζονται πίσω ως"\0".Χρήστες
sysread/syswrite: μην αναμειγνύετε τηseekμεsysreadήsyswrite. Ηseekλειτουργεί στο στρώμα ενταμιευτή PerlIO· η μη ενταμιευμένη sys-οικογένεια το παρακάμπτει, οπότε οι ενεργές τους θέσεις αποκλίνουν. Χρησιμοποιήστε τηνsysseekγια handles που προσπελάζετε μέσω της sys-οικογένειας.Offsets χαρακτήρων μέσω αριθμητικής: ο πολλαπλασιασμός καταμέτρησης χαρακτήρων με υποτιθέμενο πλάτος κωδικοποίησης είναι εσφαλμένος για
UTF-8και άλλες κωδικοποιήσεις μεταβλητού μήκους. Χρησιμοποιήστε offsets bytes που λαμβάνονται από τηνtell, ή διαβάστε προς τα εμπρός από γνωστό όριο.Handles καταλόγου: η
seekδεν λειτουργεί σε handles καταλόγου. Χρησιμοποιήστεseekdirμε θέση από τηνtelldir.Κλειστό filehandle: επιστρέφει ψευδή τιμή και θέτει το
$!· υπόuse warningsεκπέμπεται προειδοποίησηseek() on closed filehandle.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
tell- διαβάστε το τρέχον offset bytes· η τιμή κάνει πλήρη κύκλο με ασφάλεια μέσω τηςseekμεWHENCE0sysseek- μη ενταμιευμένη seek για handles που προσπελάζονται μέσωsysread/syswrite· χρησιμοποιήστε αυτή αντί τηςseekόταν παρακάμπτετε το PerlIOread- ενταμιευμένη ανάγνωση σταθερού μήκους· ο φυσικός συνεργάτης για τοποθέτηση με offset bytesreadline- γραμμοκεντρική ανάγνωση· ηseek $fh, 0, 1πριν από επανάληψη είναι το ιδίωμαtail -feof- δοκιμάστε για τέλος αρχείου· ηseekκαθαρίζει τη σημαία EOF που μπορεί να έθεσε προηγούμενη ανάγνωσηFcntl- πηγή των σταθερώνSEEK_SET,SEEK_CUR,SEEK_END