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

syswrite#

Γράφει bytes σε filehandle με την ακατέργαστη κλήση συστήματος write(2), παρακάμπτοντας το ενταμιευμένο I/O της Perl.

Η syswrite παραδίδει LENGTH bytes από το SCALAR απευθείας στον πυρήνα μέσω της write(2), παρακάμπτοντας την ενταμίευση PerlIO από την οποία περνούν οι print, printf και write. Ο πυρήνας ενδέχεται να δεχτεί λιγότερα bytes από όσα ζητήθηκαν - η syswrite επιστρέφει ό,τι όντως έγραψε, και ο καλογραμμένος κώδικας ελέγχει πάντα. Αν παραλειφθεί το LENGTH, γράφεται ολόκληρο το SCALAR. Ένα προαιρετικό OFFSET ξεκινά την εγγραφή σε θέση διαφορετική από την αρχή της συμβολοσειράς.

Σύνοψη#

syswrite FILEHANDLE, SCALAR, LENGTH, OFFSET
syswrite FILEHANDLE, SCALAR, LENGTH
syswrite FILEHANDLE, SCALAR

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

Το πλήθος των bytes που όντως γράφτηκαν, ή undef σε σφάλμα (με ρυθμισμένο το $!). Το επιστρεφόμενο πλήθος μπορεί να είναι μικρότερο από το LENGTH. Αυτό είναι φυσιολογικό σε pipes, υποδοχές, και μη μπλοκαριστικά handles· δεν είναι σφάλμα. Κώδικας που χρειάζεται να παραδώσει κάθε byte πρέπει να επαναλαμβάνει σε βρόχο:

my $off = 0;
my $len = length $buf;
while ($off < $len) {
    my $n = syswrite $fh, $buf, $len - $off, $off;
    defined $n or die "write failed: $!";
    $off += $n;
}

Επιστροφή 0 είναι νόμιμη και σημαίνει «δεν γράφτηκαν bytes σε αυτή την κλήση, ξαναπροσπαθήστε» - όχι τέλος ροής. Το undef είναι το μόνο σήμα σφάλματος.

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

  • $! - τίθεται σε σφάλμα (οποιαδήποτε επιστροφή undef).

  • Καμία αλληλεπίδραση με τα $,, $\, ή $|. Η syswrite δεν μορφοποιεί, δεν προσαρτά διαχωριστές εγγραφής, και δεν τηρεί τη σημαία autoflush επειδή δεν υπάρχει ενταμιευτής προς εκκένωση - τα bytes πηγαίνουν κατευθείαν στον πυρήνα.

  • Καμία αλληλεπίδραση με το επιλεγμένο filehandle από τη select. Το FILEHANDLE είναι υποχρεωτικό· δεν υπάρχει προεπιλογή.

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

Εγγραφή συμβολοσειράς αυτολεξεί στο STDOUT, χωρίς προσθήκη διαχωριστών:

syswrite STDOUT, "hello\n";        # 6 bytes written

Εγγραφή εγγραφής σταθερού μεγέθους και έλεγχος για σύντομη εγγραφή:

my $rec = pack "A8 N", $name, $id;   # 12 bytes
my $n = syswrite $fh, $rec;
defined $n or die "syswrite: $!";
$n == length $rec or die "short write: $n of ${\length $rec}";

Εγγραφή από τη μέση ενός ενταμιευτή με OFFSET. Χρήσιμο μέσα σε βρόχο εκκένωσης όπου το $off παρακολουθεί πόσα έχουν γίνει δεκτά μέχρι στιγμής:

my $buf = "ABCDEFGHIJ";
syswrite $fh, $buf, 4, 3;          # writes "DEFG"

Αρνητικό OFFSET μετράει από το τέλος:

my $buf = "ABCDEFGHIJ";
syswrite $fh, $buf, 3, -4;         # writes "GHI"

Εγγραφή σε μη μπλοκαριστική υποδοχή και χειρισμός του EAGAIN:

use Errno qw(EAGAIN EWOULDBLOCK);

my $n = syswrite $sock, $buf;
if (!defined $n) {
    if ($! == EAGAIN || $! == EWOULDBLOCK) {
        # kernel buffer full - try again after select()
    } else {
        die "syswrite: $!";
    }
}

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

  • Μην αναμειγνύετε με ενταμιευμένο I/O στο ίδιο handle. Η syswrite παρακάμπτει το PerlIO, αλλά οι print, printf, write, seek, tell και eof περνούν όλες από τα στρώματα ενταμίευσης :perlio και :crlf. Η διαπλοκή τους σε ένα handle αλλοιώνει τη σειρά εξόδου. Επιλέξτε μία λειτουργία ανά handle. Αν πρέπει να αναμείξετε, χρησιμοποιήστε τους κανόνες συμμετρίας read / sysread και να είστε προσεκτικοί.

  • Οι σύντομες εγγραφές είναι φυσιολογικές. Τα pipes, οι υποδοχές, τα τερματικά και τα μη μπλοκαριστικά handles τακτικά δέχονται λιγότερα bytes από αυτά που προσφέρονται. Το ιδίωμα βρόχου εκκένωσης παραπάνω είναι το σωστό μοτίβο για κάθε handle όπου οι σύντομες εγγραφές έχουν σημασία.

  • Τιμή επιστροφής 0 σημαίνει ότι ο πυρήνας δέχτηκε μηδέν bytes σε αυτή την κλήση. Δεν είναι τέλος ροής ούτε σφάλμα· επαναλάβετε.

  • Μήκος μεγαλύτερο από τα διαθέσιμα δεδομένα: αν το LENGTH υπερβαίνει το length(SCALAR) - OFFSET, γράφονται μόνο τα διαθέσιμα bytes και αυτό το πλήθος επιστρέφεται.

  • Κενό SCALAR: αν το SCALAR έχει μηδενικό μήκος, το OFFSET πρέπει να είναι 0. Οποιαδήποτε άλλη τιμή εγείρει εξαίρεση.

  • Τα στρώματα :utf8 και :encoding(...) εγείρουν εξαίρεση. Η syswrite λειτουργεί σε bytes, όχι χαρακτήρες, και αρνείται οποιοδήποτε handle φέρει στρώμα κωδικοποίησης UTF-8. Το :encoding(...) προσθέτει σιωπηρά το :utf8, οπότε απαγορεύεται εξίσου. Χρησιμοποιήστε binmode για να αφαιρέσετε το στρώμα, ή γράψτε μέσω print αντ’ αυτού.

  • Χαρακτήρες πάνω από το U+00FF σε handle λειτουργίας bytes εγείρουν επίσης εξαίρεση - δεν υπάρχει τρόπος να σειριοποιηθεί ένα codepoint μεγαλύτερο από 0xFF ως μονό byte. Κωδικοποιήστε ρητά τη συμβολοσειρά πριν την κλήση της syswrite:

    use Encode qw(encode);
    syswrite $fh, encode("UTF-8", $text);
    
  • Σπασμένο pipe / κλειστή υποδοχή εγείρει SIGPIPE. Η προεπιλεγμένη ενέργεια τερματίζει τη διεργασία. Εγκαταστήστε $SIG{PIPE} = 'IGNORE' (ή χειριστή) για να μετατρέψετε αυτό σε κανονικό σφάλμα syswrite με το $! ρυθμισμένο σε EPIPE.

  • Κλεισμένο filehandle επιστρέφει undef με το $! ρυθμισμένο σε "Bad file descriptor"· υπό use warnings εκπέμπεται προειδοποίηση syswrite() on closed filehandle.

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

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

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

  • sysread - το αντίστοιχο ανάγνωσης· ίδια σημασιολογία παράκαμψης ενταμιευτή και ίδιος επιφυλακτικός όρος για σύντομη ανάγνωση

  • sysopen - ανοίγει handle σε επίπεδο open(2) ώστε η syswrite να μπορεί να επικοινωνήσει με αυτό χωρίς να παρεμβάλλονται στρώματα μετάφρασης PerlIO

  • sysseek - επανατοποθετεί το handle χρησιμοποιώντας την lseek(2), συνδυάζεται με την syswrite για I/O τυχαίας πρόσβασης σε ακατέργαστα handles

  • print - η ενταμιευμένη αντίστοιχη που σχεδόν πάντα θέλετε αντ’ αυτής· τηρεί τα $,, $\ και $|

  • binmode - αφαιρεί στρώμα :utf8 ή :encoding(...) από handle ώστε να μπορεί να χρησιμοποιηθεί η syswrite σε αυτό

  • $! - επιθεωρήστε το μετά από επιστροφή undef για να διακρίνετε το EAGAIN από πραγματική αποτυχία