I/O · Δεδομένα σταθερού μήκους
read#
Διαβάζει σταθερή ποσότητα ενταμιευμένης εισόδου από ένα filehandle σε ένα βαθμωτό.
Η read τραβά έως LENGTH χαρακτήρες από το FILEHANDLE και τους αποθηκεύει στο SCALAR, επιστρέφοντας πόσοι διαβάστηκαν στην πραγματικότητα. Περνά μέσα από τη στοίβα PerlIO του handle και είναι επομένως ενταμιευμένη επάνω από την υποκείμενη ανάγνωση ΛΣ - σε αντίθεση με την sysread, η οποία παρακάμπτει τον ενταμιευτή και καλεί απευθείας την read(2). Το προαιρετικό όρισμα OFFSET σας επιτρέπει να μπολιάσετε τα εισερχόμενα δεδομένα στο μέσο του SCALAR αντί να το αντικαταστήσετε.
Σύνοψη#
read FILEHANDLE, SCALAR, LENGTH
read FILEHANDLE, SCALAR, LENGTH, OFFSET
Τι επιστρέφεται#
Ο αριθμός χαρακτήρων που διαβάστηκαν, ο οποίος μπορεί να είναι μικρότερος από
LENGTH.0στο τέλος του αρχείου.
Το SCALAR μεγαλώνει ή μικραίνει ώστε ο τελευταίος χαρακτήρας που διαβάστηκε πραγματικά να γίνει ο τελευταίος χαρακτήρας του βαθμωτού - εκτός αν δοθεί OFFSET, οπότε αντικαθίσταται μόνο το τμήμα στη θέση OFFSET και ό,τι βρίσκεται πέρα από αυτό αφήνεται ως έχει (δείτε Το όρισμα OFFSET παρακάτω).
Μια σύντομη ανάγνωση δεν αποτελεί σφάλμα. Σε κανονικό αρχείο σημαίνει συνήθως ότι φτάσατε στο τέλος του αρχείου· σε σωλήνα, υποδοχή ή τερματικό σημαίνει ότι δεν υπάρχουν άλλα δεδομένα διαθέσιμα αυτή τη στιγμή. Επαναλάβετε σε βρόχο μέχρι είτε να έχετε τα bytes που χρειάζεστε είτε η read να επιστρέψει 0 / undef:
my $buf = "";
my $want = 4096;
while ($want > 0) {
my $got = read($fh, $buf, $want, length $buf);
die "read error: $!" unless defined $got;
last if $got == 0; # EOF
$want -= $got;
}
Καθολική κατάσταση που επηρεάζει#
${^UTF8CACHE}/ τα στρώματα PerlIO του handle - καθορίζουν αν τοLENGTHμετράται σε bytes ή σε χαρακτήρες (δείτε Σημασιολογία χαρακτήρων έναντι bytes παρακάτω).
Η read δεν αλληλεπιδρά με τα $_, $/, $\, ή $,. Σε αντίθεση με την readline, δεν ενδιαφέρεται για τον διαχωριστή εγγραφών εισόδου.
Το όρισμα OFFSET#
Το OFFSET ελέγχει πού μέσα στο SCALAR προσγειώνονται τα εισερχόμενα δεδομένα. Δεν κάνει αναζήτηση στο filehandle.
Παραλειπόμενο - τα δεδομένα αντικαθιστούν ολόκληρο το περιεχόμενο του
SCALAR.Θετικό, εντός μήκους - τα δεδομένα γράφονται ξεκινώντας από τη θέση
OFFSET. Οι χαρακτήρες πριν τοOFFSETδιατηρούνται· οι χαρακτήρες από τοOFFSETμέχρι το τέλος τουSCALARαντικαθίστανται ή επεκτείνονται.Θετικό, πέρα από το μήκος - το
SCALARγεμίζεται πρώτα με bytes"\0"μέχρι τοOFFSET, και έπειτα προσαρτάται η ανάγνωση. Χρήσιμο για ανάγνωση σε σταθερή θέση μέσα σε μεγαλύτερο ενταμιευτή που συναρμολογείτε.Αρνητικό - μετρά αντίστροφα από το τέλος του
SCALAR. Το-1σημαίνει «αντικατάσταση του τελευταίου χαρακτήρα και προσάρτηση από εκεί».
my $buf = "HEADER";
read($fh, $buf, 16, length $buf); # append 16 chars after "HEADER"
my $slab = "";
read($fh, $slab, 512, 1024); # pad to 1024 "\0" bytes, then
# read 512 chars - $slab is
# now 1536 chars long
Σημασιολογία χαρακτήρων έναντι bytes#
Το LENGTH μετράται σε όποια μονάδα διαχειρίζεται το handle:
Handle σε λειτουργία bytes (η προεπιλογή, και κάθε handle που ανοίγεται χωρίς στρώμα κωδικοποίησης): το
LENGTHείναι αριθμός bytes. Τοread($fh, $buf, 10)τραβά 10 bytes και τοlength $bufείναι 10.Στρώμα
:utf8: τοLENGTHείναι αριθμός χαρακτήρων. Η Perl αποκωδικοποιεί UTF-8 κατά την είσοδο, και το$bufκρατά αποκωδικοποιημένα code points. Ο αριθμός bytes που καταναλώνονται από το αρχείο μπορεί να κυμαίνεται απόLENGTHέως4 * LENGTH, ανάλογα με το κείμενο.Στρώμα
:encoding(...): ίδιος κανόνας με το:utf8, για οποιαδήποτε κωδικοποίηση γνωρίζει το στρώμα.
open my $fh, "<:utf8", "greek.txt" or die $!;
read($fh, my $buf, 5); # 5 characters, not 5 bytes
Η ανάμειξη ανάγνωσης σε λειτουργία bytes με δεδομένα UTF-8 παράγει mojibake και, υπό το use warnings, μια προειδοποίηση Malformed UTF-8 αν αποκωδικοποιήσετε αργότερα το αποτέλεσμα. Επιλέξτε το στρώμα κατά τη στιγμή του open και μείνετε σε αυτό.
I/O με ενταμιευτή έναντι χωρίς ενταμιευτή#
Η read είναι stdio-ενταμιευμένη μέσω PerlIO - εσωτερικά καλεί fread(3) (ή την αντικατάστασή της από το PerlIO) στον ενταμιευτή του handle. Αυτό έχει δύο συνέπειες που αξίζει να θυμάστε:
Μπορείτε να αναμείξετε ελεύθερα τις
read,readline/<$fh>,getcκαιseekστο ίδιο handle. Όλες βλέπουν τον ίδιο ενταμιευτή.Δεν πρέπει να αναμείξετε τη
readμε τηsysreadστο ίδιο handle. Ηsysreadπαρακάμπτει τον ενταμιευτή και πάει κατευθείαν στηνread(2)· οποιαδήποτε bytes έχουν ήδη τραβηχτεί στον ενταμιευτή από προηγούμενηreadγίνονται αόρατα στηνsysread, και αντιστρόφως. Αν χρειάζεστε σημασιολογία πρωτογενούς κλήσης συστήματος, χρησιμοποιήστε αποκλειστικάsysreadσε αυτό το handle.
Για είσοδο ακριβείας bytes, χωρίς ενταμιευτή - για παράδειγμα σε μη μπλοκάρουσα υποδοχή, ή όταν υλοποιείτε πρωτόκολλο όπου μια σύντομη ανάγνωση έχει νόημα και δεν είναι «δοκίμασε ξανά» - καταφύγετε στη sysread.
Παραδείγματα#
Ανάγνωση κεφαλίδας σταθερού μεγέθους από δυαδικό αρχείο:
open my $fh, "<", "packet.bin" or die "open: $!";
binmode $fh;
my $header;
my $n = read($fh, $header, 16);
die "short header: got $n bytes" unless $n == 16;
Προσάρτηση 16 bytes στο τέλος υπάρχοντος ενταμιευτή χρησιμοποιώντας OFFSET ίσο με το τρέχον μήκος:
my $buf = "PRELUDE:";
read($fh, $buf, 16, length $buf); # $buf is now "PRELUDE:" . 16 new bytes
Ανάγνωση στη θέση 1024 ενός βαθμωτού, γεμίζοντας το κενό με "\0":
my $slot = "";
read($fh, $slot, 64, 1024); # length($slot) == 1088
# substr($slot, 0, 1024) is "\0" x 1024
Επαναλάβετε σε βρόχο μέχρι να έχετε ακριβώς N bytes ή να φτάσετε σε EOF - το σωστό μοτίβο για σωλήνες και υποδοχές όπου μια μεμονωμένη read συχνά επιστρέφει λιγότερα bytes από όσα ζητούνται:
sub read_exact {
my ($fh, $n) = @_;
my $buf = "";
while (length($buf) < $n) {
my $got = read($fh, $buf, $n - length($buf), length $buf);
return undef unless defined $got;
return $buf if $got == 0; # EOF; caller inspects length
# loop
}
return $buf;
}
Ανάγνωση μετρημένη σε χαρακτήρες μέσω στρώματος UTF-8:
open my $fh, "<:encoding(UTF-8)", "notes.txt" or die $!;
read($fh, my $chunk, 100); # 100 characters
printf "chars=%d bytes=%d\n", length $chunk, do {
use bytes; length $chunk;
};
Οριακές περιπτώσεις#
Κλειστό filehandle: επιστρέφει
undefκαι ορίζει το$!σε"Bad file descriptor". Υπό τοuse warningsεκπέμπεται προειδοποίησηread() on closed filehandle.Μη ανοιγμένο filehandle: ίδιο με κλειστό -
undefκαι ορίζεται το$!.LENGTHίσο με0: ηreadεπιστρέφει αμέσως0και δεν αγγίζει τοSCALAR. Δεν είναι αξιόπιστη ανίχνευση EOF· χρησιμοποιήστεeofγι” αυτό.Αρνητικό
LENGTH: μοιραίο σφάλμα κατά τον χρόνο εκτέλεσης (Negative length at ...). Επικυρώστε τοLENGTHπριν την κλήση.Αρνητικό
OFFSETτου οποίου το μέτρο υπερβαίνει το τρέχον μήκος τουSCALAR: μοιραίο σφάλμα κατά τον χρόνο εκτέλεσης (Offset outside string). Περιορίστε μεmax($offset, -length $buf)όταν το offset υπολογίζεται.Σύντομη ανάγνωση σε σωλήνα ή υποδοχή: δεν είναι σφάλμα. Η
readεπιστρέφει λιγότερους χαρακτήρες από όσους ζητήθηκαν όποτε ο ενταμιευτής PerlIO αδειάζει πριν φτάσει τοLENGTH. Επαναλάβετε σε βρόχο αν χρειάζεστε τον πλήρη αριθμό.EOF στη μέση της ανάγνωσης: επιστρέφει το μερικό πλήθος. Η επόμενη κλήση επιστρέφει
0. Μετά από αυτό, το$fhπαραμένει σε EOF μέχρι να κάνετεseekήclearerr.Ανάγνωση από συνδεδεμένο (tied) handle: η
readαποστέλλεται στη μέθοδοREADτης κλάσης tie, η οποία είναι υπεύθυνη να τιμά ταLENGTHκαιOFFSET. Κακά συμπεριφερόμενες κλάσεις tie μπορούν να παραβιάσουν τη σύμβαση «μεγάλωσε τοSCALARώστε ο τελευταίος χαρακτήρας που διαβάστηκε να είναι ο τελευταίος χαρακτήρας».Αλληλεπίδραση με
sysread: μην τις αναμείξετε σε ένα handle. Ηreadγεμίζει τον ενταμιευτή PerlIO σε τμήματα της επιλογής της· ηsysreadαγνοεί αυτόν τον ενταμιευτή εντελώς.Δυαδικά δεδομένα σε handle λειτουργίας κειμένου: σε συστήματα Unix-like δεν υπάρχει ξεχωριστή λειτουργία κειμένου, αλλά ένα στρώμα κωδικοποίησης εξακολουθεί να μετασχηματίζει bytes. Χρησιμοποιήστε
binmode $fh(ήopen ..., "<:raw", ...) πριν διαβάσετε δυαδικά δεδομένα.FILEHANDLEως έκφραση: bareword ή απλό βαθμωτό είναι εντάξει. Οτιδήποτε πιο σύνθετο πρέπει να μπει σε παρενθέσεις:read(($handles[$i]), $buf, $len).
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
open- αποκτά το filehandle και αποφασίζει αν οι επόμενεςreadμετρούνται σε bytes ή σε χαρακτήρες μέσω του στρώματος I/Osysread- το αντίστοιχο χωρίς ενταμιευτή, απευθείας κλήση συστήματοςread(2)· χρησιμοποιήστε το για μη μπλοκάρουσα I/O ή όταν μια σύντομη ανάγνωση έχει νόημαreadline/<$fh>- είσοδος προσανατολισμένη σε εγγραφές που σέβεται το$/αντί για πλήθος bytes/χαρακτήρωνgetc- διαβάζει έναν μόνο χαρακτήρα· περίπουread($fh, $c, 1)αλλά με διαφορετική αναφορά EOF/undefbinmode- αφαιρεί ή προσθέτει στρώματα I/O ώστε τοLENGTHνα είναι μονοσήμαντα πλήθος bytes ή πλήθος χαρακτήρωνeof- ο σωστός τρόπος ελέγχου για τέλος αρχείου, αντί να διαβάζετε τμήμα μηδενικού μήκους