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 στο τέλος του αρχείου.

  • undef σε σφάλμα, με ορισμένο το $!.

Το 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;
}

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

  • $! - ορίζεται όταν η read επιστρέφει undef.

  • ${^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 $fhopen ..., "<:raw", ...) πριν διαβάσετε δυαδικά δεδομένα.

  • FILEHANDLE ως έκφραση: bareword ή απλό βαθμωτό είναι εντάξει. Οτιδήποτε πιο σύνθετο πρέπει να μπει σε παρενθέσεις: read(($handles[$i]), $buf, $len).

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

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

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

  • open - αποκτά το filehandle και αποφασίζει αν οι επόμενες read μετρούνται σε bytes ή σε χαρακτήρες μέσω του στρώματος I/O

  • sysread - το αντίστοιχο χωρίς ενταμιευτή, απευθείας κλήση συστήματος read(2)· χρησιμοποιήστε το για μη μπλοκάρουσα I/O ή όταν μια σύντομη ανάγνωση έχει νόημα

  • readline / <$fh> - είσοδος προσανατολισμένη σε εγγραφές που σέβεται το $/ αντί για πλήθος bytes/χαρακτήρων

  • getc - διαβάζει έναν μόνο χαρακτήρα· περίπου read($fh, $c, 1) αλλά με διαφορετική αναφορά EOF/undef

  • binmode - αφαιρεί ή προσθέτει στρώματα I/O ώστε το LENGTH να είναι μονοσήμαντα πλήθος bytes ή πλήθος χαρακτήρων

  • eof - ο σωστός τρόπος ελέγχου για τέλος αρχείου, αντί να διαβάζετε τμήμα μηδενικού μήκους