I/O

tell#

Επιστρέφει την τρέχουσα θέση σε bytes ενός filehandle.

Η tell αναφέρει πού θα γίνει η επόμενη ανάγνωση ή εγγραφή στο FILEHANDLE, μετρημένη σε bytes από την αρχή του αρχείου. Ζευγαρώστε την με την seek για να αποθηκεύσετε μια θέση τώρα και να επιστρέψετε σε αυτήν αργότερα. Αν παραλειφθεί το FILEHANDLE, η tell αναφέρει τη θέση του handle από το οποίο διαβάστηκε τελευταία - συμπεριλαμβανομένου του σιωπηρού handle μέσα σε βρόχους while (<FH>).

Σύνοψη#

tell FILEHANDLE
tell

Τι επιστρέφεται#

Μη αρνητικό ακέραιο byte offset σε επιτυχία, -1 σε σφάλμα. Η τιμή είναι κατάλληλη ως όρισμα POSITION προς την seek με WHENCE στο 0 (απόλυτη μετάβαση). Σε pipes, FIFOs, υποδοχές, και μερικές φορές στις τυπικές ροές, το υποκείμενο OS δεν έχει θέση επανατοποθέτησης και η 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

Καθολική κατάσταση που επηρεάζει#

  • Filehandle τελευταίας ανάγνωσης: η μορφή tell χωρίς όρισμα χρησιμοποιεί το handle από το οποίο έγινε η πιο πρόσφατη ανάγνωση στην τρέχουσα εμβέλεια. Κάθε readline, <FH>, ή <> το ενημερώνει. Η ανάμιξη της tell χωρίς όρισμα με πολλαπλά ενεργά handles είναι πηγή απρόσμενων αποτελεσμάτων - ονομάστε ρητά το handle όταν αμφιβάλλετε.

  • Το $! δεν είναι αξιόπιστο κανάλι σφαλμάτων εδώ. Ελέγξτε για -1 απευθείας αντί να ελέγξετε το $! μετά την κλήση.

Bytes, όχι χαρακτήρες#

Η tell επιστρέφει πάντα byte offset, ακόμα κι όταν το handle έχει στρώμα PerlIO προσανατολισμένο σε χαρακτήρες όπως :encoding(UTF-8) ή :utf8. Αυτό είναι σκόπιμο: η μετατροπή μέτρησης χαρακτήρων σε byte offset σε κωδικοποίηση μεταβλητού πλάτους θα απαιτούσε επανάγνωση του αρχείου από την αρχή. Ο ίδιος κανόνας ισχύει για τις seek και sysseek - όλες μιλούν με bytes.

Συνέπεια: σε αρχείο κειμένου 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

Η μορφή χωρίς όρισμα χρησιμοποιεί το handle από το οποίο διαβάστηκε τελευταία. Μέσα σε βρόχο while (<>) αυτό το handle είναι το σιωπηρό ARGV:

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

Η tell σε pipe επιστρέφει -1 επειδή τα pipes δεν είναι επανατοποθετήσιμα:

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

Filehandles μέσα σε σύνθετες εκφράσεις χρειάζονται την ίδια μορφή μπλοκ όπως με την print - η tell $handles[0] είναι συντακτικό σφάλμα. Χρησιμοποιήστε:

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

Οριακές περιπτώσεις#

  • Κλειστό filehandle: επιστρέφει -1. Υπό use warnings εκπέμπεται προειδοποίηση tell() on closed filehandle.

  • Μορφή χωρίς όρισμα, καμία ανάγνωση ακόμα: επιστρέφει -1. Το «filehandle τελευταίας ανάγνωσης» έχει νόημα μόνο μετά από πραγματική ανάγνωση.

  • Μετά από sysread / syswrite / sysseek: μη χρησιμοποιείτε την tell σε handle που έχετε χειριστεί με την οικογένεια sys*. Αυτές οι συναρτήσεις παρακάμπτουν το buffering του PerlIO· η tell αναφέρει την ενταμιευμένη θέση, που θα είναι λάθος κατά τα περιεχόμενα του ενταμιευτή. Χρησιμοποιήστε sysseek με whence 1 και offset 0 ως την ασφαλή για sys* ερώτηση θέσης.

  • Τυπικές ροές: οι tell STDIN, tell STDOUT, tell STDERR μπορεί να επιστρέψουν -1 ή ένα ουσιαστικό offset ανάλογα με το αν η ροή στηρίζεται σε κανονικό αρχείο (ανακατεύθυνση κελύφους) ή σε τερματικό, pipe, ή υποδοχή.

  • Δεν υπάρχει systell: δεν υπάρχει ξεχωριστή συνάρτηση για θέση που παρακάμπτει το buffering. Το ιδίωμα είναι:

    my $pos = sysseek $fh, 0, 1;
    
  • Δυαδική κατάσταση έναντι κατάστασης κειμένου σε μη-Linux πλατφόρμες: η pperl στοχεύει μόνο το Linux, οπότε τα offsets της tell ταιριάζουν πάντα με τα ωμά bytes του αρχείου. Στρώματα μετατροπής CRLF που περιπλέκουν την tell σε perls οικογένειας Windows δεν εφαρμόζονται εδώ.

  • Κατάσταση προσάρτησης (>>): μετά από open my $fh, ">>", ..., η αρχική tell $fh μπορεί να αναφέρει 0 μέχρι την πρώτη εγγραφή, επειδή ορισμένες πλατφόρμες τοποθετούν το handle στο τέλος του αρχείου μόνο σε κάθε εγγραφή. Μη βασίζεστε στην αρχική θέση· γράψτε μία φορά, μετά κάντε tell.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • seek - άλμα σε απόλυτο byte offset που είχε επιστρέψει προηγουμένως η tell

  • sysseek - ερώτηση και άλμα θέσης για handles που χρησιμοποιούνται με sysread / syswrite, παρακάμπτοντας το buffering του PerlIO

  • telldir - το αντίστοιχο για handle καταλόγου· ζευγαρώνει με seekdir

  • eof - έλεγχος για τέλος αρχείου αντί για απόλυτη θέση

  • open - δημιουργία του filehandle εξαρχής· το mode και τα στρώματα PerlIO καθορίζουν αν το handle είναι επανατοποθετήσιμο