I/O · Δεδομένα σταθερού μήκους

sysread#

Διαβάζει ωμά bytes από ένα filehandle καλώντας την υποκείμενη κλήση συστήματος read(2).

Η sysread προσπαθεί να διαβάσει LENGTH bytes από το FILEHANDLE και να τα αποθηκεύσει στο SCALAR. Παρακάμπτει τη στοίβα ενταμίευσης του PerlIO, που είναι ο όλος σκοπός - οι αναγνώσεις πηγαίνουν κατευθείαν στον πυρήνα και επιστρέφουν ό,τι επιστρέφει μία μεμονωμένη read(2), που μπορεί να είναι λιγότερα bytes από αυτά που ζητήθηκαν. Χρησιμοποιήστε την για υποδοχές, σωλήνες, συσκευές και κάθε άλλη κατάσταση όπου θέλετε έλεγχο πάνω σε μεμονωμένες κλήσεις συστήματος αντί για είσοδο προσανατολισμένη σε γραμμή ή εγγραφή.

Σύνοψη#

sysread FILEHANDLE, SCALAR, LENGTH
sysread FILEHANDLE, SCALAR, LENGTH, OFFSET

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

  • Ο αριθμός των bytes που διαβάστηκαν πραγματικά, που μπορεί να είναι λιγότερα από το LENGTH σε υποδοχές, σωλήνες, ttys και κατά τη διάρκεια διακοπής από σήμα.

  • 0 στο τέλος αρχείου.

  • undef σε σφάλμα, με την $! ορισμένη στην errno της αποτυχημένης read(2).

Το SCALAR μεγαλώνει ή συρρικνώνεται ώστε το τελευταίο byte που διαβάστηκε να γίνει το τελευταίο byte του βαθμωτού. Μετά από σύντομη ανάγνωση, το βαθμωτό κρατά μόνο τα bytes που ελήφθησαν πραγματικά - τίποτα δεν συμπληρώνεται με μηδενικά μέχρι το LENGTH.

my $n = sysread $sock, my $buf, 4096;
defined $n           or die "read failed: $!";
$n == 0              and return;          # peer closed
process_chunk($buf);                      # length($buf) == $n

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

  • $! - τίθεται όταν η sysread επιστρέφει undef. Οι διακοπείσες αναγνώσεις εμφανίζονται ως EINTR· οι αναγνώσεις που θα μπλόκαραν σε μη μπλοκαριστικά handles εμφανίζονται ως EAGAIN / EWOULDBLOCK.

  • Το ίδιο το SCALAR - του γίνεται πάντα ανάθεση, ακόμη και σε αποτυχία (αποκόπτεται σε OFFSET bytes όταν δίνεται OFFSET και η ανάγνωση αποτυγχάνει ή επιστρέφει μηδέν).

  • Η θέση byte του filehandle προωθείται κατά τον αριθμό των bytes που επιστράφηκαν· αυτή είναι η ίδια θέση σε επίπεδο πυρήνα που χειρίζεται η sysseek.

Η sysread δεν συμβουλεύεται ούτε αγγίζει τις $/, $\, $,, ή $_. Είναι πρωτογενής λειτουργία επιπέδου byte· η σημασιολογία εγγραφών δεν εφαρμόζεται.

OFFSET - πού προσγειώνονται τα bytes μέσα στο SCALAR#

Χωρίς OFFSET, το SCALAR αντικαθίσταται από τα bytes που διαβάστηκαν.

Με OFFSET, τα bytes γράφονται μέσα στο SCALAR ξεκινώντας από εκείνη τη θέση:

  • OFFSET >= 0 - αρχίζει η εγγραφή στο byte OFFSET. Αν το OFFSET είναι μεγαλύτερο από το τρέχον μήκος του SCALAR, η συμβολοσειρά συμπληρώνεται πρώτα με "\0" bytes μέχρι το OFFSET, και κατόπιν προστίθενται τα νέα δεδομένα.

  • OFFSET < 0 - μετριέται προς τα πίσω από το τέλος του SCALAR. Το -1 σημαίνει «αντικατάσταση του τελευταίου byte», το -10 σημαίνει «αντικατάσταση των τελευταίων 10 bytes».

Έτσι μεγαλώνετε σταδιακά έναν ενταμιευτή χωρίς επαναλαμβανόμενη συνένωση:

my $buf = "";
while ((my $n = sysread $fh, $buf, 8192, length $buf) > 0) {
    # each call appends at the current end of $buf
}
defined $n or die "read failed: $!";

Παραδείγματα#

Ανάγνωση έως 64 bytes από αρχείο. Το $buf καταλήγει ακριβώς $n bytes σε μήκος:

open my $fh, "<", "input.bin" or die $!;
my $n = sysread $fh, my $buf, 64;
defined $n or die "sysread: $!";

Ανάγνωση έως 32 bytes και τοποθέτησή τους ξεκινώντας από τη θέση 512 στο $buf, με συμπλήρωση "\0" αν το $buf ήταν μικρότερο:

my $buf = "header";
my $n = sysread $fh, $buf, 32, 512;   # $buf is now 512 + $n bytes

Αποστράγγιση υποδοχής μέχρι να κλείσει ο ομότιμος. Ο έλεγχος για 0 - όχι για eof - είναι ο μόνος σωστός έλεγχος τέλους ροής για την sysread:

while (1) {
    my $n = sysread $sock, my $chunk, 4096;
    defined $n or die "read: $!";
    last if $n == 0;                  # orderly shutdown from peer
    handle($chunk);
}

Επανεκκίνηση ανάγνωσης που διέκοψε σήμα. Σε μπλοκαριστικό handle, το EINTR είναι η μία αποτυχία που τυπικά επανεπιχειρείτε αντί να διαδώσετε:

use Errno qw(EINTR);
my $n;
RETRY: {
    $n = sysread $fh, my $buf, $want;
    redo RETRY if !defined $n && $! == EINTR;
}
defined $n or die "read: $!";

Γέμισμα εγγραφής σταθερού μεγέθους, ανεκτικά απέναντι σε σύντομες αναγνώσεις. Μία sysread μπορεί να επιστρέψει λιγότερα bytes από όσα ζητήθηκαν ακόμη και σε κανονικό αρχείο κοντά στο EOF, και τακτικά το κάνει σε υποδοχές και σωλήνες:

sub read_exact {
    my ($fh, $want) = @_;
    my $buf = "";
    while (length($buf) < $want) {
        my $n = sysread $fh, $buf, $want - length($buf), length $buf;
        defined $n        or die "read: $!";
        $n == 0 and die "short read: got ", length $buf, " of $want";
    }
    return $buf;
}

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

  • Ποτέ μην αναμιγνύετε με ενταμιευμένο I/O στο ίδιο handle. Οι readline, read, <$fh>, getc, eof, seek και tell περνούν όλες από ενταμιευτές PerlIO· η sysread τους παρακάμπτει. Η διαπλοκή τους στο ίδιο handle αφήνει δεδομένα εγκλωβισμένα στον ενταμιευτή που η sysread δεν θα δει ποτέ, ή προσπερνά δεδομένα που ο ενταμιευμένος αναγνώστης κατανάλωσε ήδη. Χρησιμοποιήστε ένα στυλ ανά handle.

  • Το :utf8 απαγορεύεται. Handle με στρώμα :utf8 (συμπεριλαμβανομένου του έμμεσου στρώματος που προστίθεται από το :encoding(...)) κάνει την sysread να εκτοξεύσει εξαίρεση. Αφαιρέστε το στρώμα με binmode - η binmode $fh χωρίς δεύτερο όρισμα επαναφέρει ωμά bytes - πριν καλέσετε την sysread.

  • Το :crlf / :perlio εντάμιεύουν παρ” όλα αυτά. Ακόμη και χωρίς :utf8, η προεπιλεγμένη στοίβα :perlio εντάμιεύει αναγνώσεις και μεταφράζει τερματισμούς γραμμών υπό :crlf. Η sysread αγνοεί εκείνα τα στρώματα, οπότε bytes που ο ενταμιευμένος αναγνώστης τράβηξε ήδη στον ενταμιευτή PerlIO χάνονται σιωπηρά για την sysread. Ανοίξτε handles προοριζόμενα για sysread με sysopen ή καλέστε binmode $fh για να απενεργοποιήσετε το :crlf.

  • Οι σύντομες αναγνώσεις είναι κανονικές, όχι σφάλματα. Επιστροφή $n με 0 < $n < LENGTH είναι επιτυχία. Μόνο το undef υποδηλώνει αποτυχία· το 0 υποδηλώνει EOF. Κάντε βρόχο μέχρι να έχετε ό,τι χρειάζεστε.

  • Δεν υπάρχει syseof. Δεν υπάρχει ξεχωριστός έλεγχος τέλους-αρχείου για την sysread· η eof κοιτά τον ενταμιευτή PerlIO και είναι άνευ νοήματος εδώ. Η τιμή επιστροφής 0 είναι το σήμα τέλους-αρχείου.

  • OFFSET πέρα από το τρέχον μήκος. Η sysread $fh, $buf, 10, 1_000_000 συμπληρώνει το $buf με ένα εκατομμύριο "\0" bytes πριν γράψει. Αυτό είναι περιστασιακά χρήσιμο για προ-δέσμευση, αλλά συνήθως είναι σφάλμα.

  • Το αρνητικό OFFSET μετριέται από το τρέχον τέλος του SCALAR, όχι από το LENGTH. Η sysread $fh, $buf, 4, -4 αντικαθιστά τα τελευταία τέσσερα bytes ό,τι κρατά αυτή τη στιγμή το $buf.

  • Μη μπλοκαριστικά handles. Σε handle με O_NONBLOCK ορισμένο, μια ανάγνωση χωρίς διαθέσιμα δεδομένα επιστρέφει undef με την $! ίση με EAGAIN ή EWOULDBLOCK. Αντιμετωπίστε το ως «δοκιμάστε αργότερα», όχι ως σφάλμα.

  • Σήματα. Μια μπλοκαριστική sysread που διακόπτεται από σήμα επιστρέφει undef με την $! ίση με EINTR. Επαναλάβετε την κλήση.

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

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

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

  • syswrite - το αντίστοιχο της πλευράς εγγραφής· ίδιοι κανόνες ενταμίευσης, ίδια σημασιολογία σύντομου I/O

  • sysopen - ανοίγει handle με ωμές σημαίες open(2), ο φυσικός συνεργάτης της sysread σε αρχεία

  • sysseek - αναζήτηση ακριβείας byte που συντίθεται σωστά με την sysread· μην αναμιγνύετε seek με sysread

  • read - το ενταμιευμένο αντίστοιχο· χρησιμοποιήστε την για είσοδο προσανατολισμένη σε γραμμή ή εγγραφή, όχι για υποδοχές ή μερικές αναγνώσεις

  • binmode - αφαιρεί :utf8 ή :crlf από handle πριν τη χρήση της sysread

  • $! - η τιμή errno μετά από αποτυχημένη sysread, συμπεριλαμβανομένων των EINTR, EAGAIN και EWOULDBLOCK