I/O

close#

Κλείνει ένα filehandle, εκκενώνει τους ενταμιευτές του και απελευθερώνει τον υποκείμενο περιγραφέα αρχείου.

Η close ολοκληρώνει όποιο I/O εκκρεμούσε στο FILEHANDLE, αποδομεί τη στοίβα στρωμάτων PerlIO και ζητά από τον πυρήνα να κλείσει τον περιγραφέα. Η τιμή επιστροφής διακρίνει το καθαρό κλείσιμο από μια περίπτωση όπου είτε μια ενταμιευμένη εγγραφή απέτυχε κατά την έξοδο, είτε ένα στρώμα PerlIO ανέφερε σφάλμα, είτε - για σωλήνες - η διεργασία-παιδί τερμάτισε με μη μηδενικό κωδικό. Χωρίς όρισμα, η close λειτουργεί στο τρέχον επιλεγμένο filehandle (βλ. select).

Σύνοψη#

close FILEHANDLE
close EXPR
close

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

Αληθής τιμή (1) σε καθαρό κλείσιμο· ψευδής τιμή διαφορετικά. Η ψευδής επιστροφή σημαίνει ότι κάτι από τα παρακάτω πήγε στραβά:

  • Μια εκκρεμής ενταμιευμένη εγγραφή δεν μπόρεσε να εκκενωθεί (πλήρης δίσκος, σπασμένος σωλήνας, κλειστή υποδοχή).

  • Ένα στρώμα PerlIO (π.χ. :encoding(...), :gzip από στρώμα του CPAN) ανέφερε σφάλμα.

  • Είχε ήδη καταγραφεί προϋπάρχον επίμονο σφάλμα στο handle.

  • Το handle προήλθε από open μέσω σωλήνα και το παιδί τερμάτισε με μη μηδενικό κωδικό (ή απέτυχε άλλη κλήση συστήματος εμπλεκόμενη στην αποδόμηση του σωλήνα).

Όταν η close επιστρέψει ψευδή τιμή, η $! κρατά το σφάλμα της αποτυχημένης λειτουργίας και διαβάζεται με ασφάλεια. Για handles σωλήνα, αν το μόνο πρόβλημα ήταν μη μηδενικός τερματισμός του παιδιού, η $! τίθεται σε 0 και η κατάσταση του παιδιού εμφανίζεται στην $? (βλ. παρακάτω).

Ελέγχετε πάντα την τιμή επιστροφής σε εγγράψιμα handles: το τελικό ενταμιευμένο μπλοκ εκκενώνεται μέσα στην close, οπότε η print που επέστρεψε αληθή τιμή νωρίτερα δεν εγγυάται ότι τα δεδομένα έφτασαν στον δίσκο.

close $fh
    or die "close $path failed: $!";

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

  • $! - τίθεται στο errno της αποτυχίας όταν η close επιστρέφει ψευδή τιμή, συμπεριλαμβανομένου του σφάλματος εκκένωσης κατά την τελική ενταμιευμένη εγγραφή. Καθαρίζεται σε 0 σε κλείσιμο σωλήνα όπου το μόνο πρόβλημα ήταν ο μη μηδενικός τερματισμός του παιδιού.

  • $? - για handles από open μέσω σωλήνα, τίθεται στην κατάσταση αναμονής της διεργασίας-παιδιού: τα 8 κατώτερα bits είναι το σήμα, τα 8 ανώτερα bits είναι ο κωδικός εξόδου (ίδια κωδικοποίηση με την system).

  • ${^CHILD_ERROR_NATIVE} - για handles σωλήνα, τίθεται στην ωμή OS-native τιμή κατάστασης (πριν τη φορητή κωδικοποίηση της Perl).

  • $. - μια ρητή close σε handle εισόδου μηδενίζει τον τρέχοντα αριθμό γραμμής. Ένα έμμεσο κλείσιμο μέσω επανανοίγματος του ίδιου handle όχι.

  • Τρέχον επιλεγμένο filehandle (μέσω select) - η close χωρίς όρισμα το κλείνει.

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

Κλείσιμο κανονικού αρχείου και έλεγχος για αποτυχία εκκένωσης:

open my $fh, ">", "out.txt" or die $!;
print {$fh} @records;
close $fh or die "flush to out.txt failed: $!";

Κλείσιμο σωλήνα ανοιγμένου για εγγραφή και επιθεώρηση της κατάστασης εξόδου του παιδιού. Η close περιμένει το παιδί και κατόπιν συμπληρώνει την $?:

open(my $sort, "|-", "sort", ">", "foo")
    or die "can't start sort: $!";
# ... print records to $sort ...
close $sort
    or warn $! ? "error closing sort pipe: $!"
               : "sort exited with status " . ($? >> 8);

Κλείσιμο σωλήνα ανοιγμένου για ανάγνωση και κατόπιν συλλογή της κατάστασης εξόδου της εντολής. Ο κωδικός εξόδου είναι τα 8 ανώτερα bits της $?:

open(my $who, "-|", "who") or die $!;
my @lines = <$who>;
close $who;
my $exit = $? >> 8;

Η γυμνή close κλείνει όποιο handle έκανε πιο πρόσφατα τρέχον η select, και κατόπιν επαναφέρει το STDOUT ως το επιλεγμένο handle:

open my $log, ">>", "app.log" or die $!;
my $old = select $log;
print "entry\n";
close;                       # closes $log (the selected handle)
select $old;

Το πρόωρο κλείσιμο του άκρου ανάγνωσης ενός σωλήνα κάνει τον εγγραφέα να λάβει SIGPIPE. Αν ο εγγραφέας δεν έχει χειριστή, θα τερματιστεί - αποστραγγίστε πρώτα τον σωλήνα αν χρειάζεστε ο εγγραφέας να εξέλθει καθαρά:

open my $gen, "-|", "some-producer" or die $!;
while (<$gen>) { last if /^END/ }
1 while <$gen>;              # drain so the child finishes cleanly
close $gen or warn "producer failed: $!";

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

  • Γυμνή close - χωρίς όρισμα, κλείνει το τρέχον επιλεγμένο filehandle. Σε ένα μόλις ξεκινημένο πρόγραμμα αυτό είναι το STDOUT· μετά από select($fh) είναι το $fh. Σπάνια αυτό που θέλετε εκτός κώδικα με στενή εμβέλεια.

  • Το επανάνοιγμα κλείνει για εσάς - η open my $fh, ... σε handle που είναι ήδη ανοιχτό θα κλείσει πρώτα τον παλιό περιγραφέα. Το έμμεσο κλείσιμο δεν μηδενίζει την $.· η ρητή close το κάνει. Χρησιμοποιήστε ρητή close όταν η κατάσταση του αριθμού γραμμής έχει σημασία.

  • Η έξοδος από την εμβέλεια κλείνει τα λεξιλογικά handles - όταν η τελευταία αναφορά σε ένα λεξιλογικό filehandle βγει εκτός εμβέλειας, η Perl το κλείνει. Αν αυτό το έμμεσο κλείσιμο αποτύχει (σφάλμα εκκένωσης, μη μηδενική έξοδος του παιδιού), η Perl εκπέμπει προειδοποίηση Warning: unable to close filehandle %s properly. Καλέστε ρητά την close σε σημείο όπου μπορείτε να ελέγξετε την τιμή επιστροφής και να σιγάσετε αυτή την προειδοποίηση.

  • Έμμεσα handles - το FILEHANDLE μπορεί να είναι οποιαδήποτε έκφραση που παράγει χρησιμοποιήσιμο filehandle: ένα bareword (close STDERR), ένα βαθμωτό (close $fh), μια αναφορά glob (close \*FH) ή ένα αυτο-δημιουργημένο handle από open my $fh, ....

  • Το κλείσιμο σωλήνα περιμένει - το κλείσιμο handle σωλήνα μπλοκάρει μέχρι να εξέλθει το παιδί, οπότε η $? έχει συμπληρωθεί όταν επιστρέφει η close. Υπό threads, αν το ίδιο handle σωλήνα παραμένει ανοιχτό σε άλλο thread, η close επιστρέφει αληθή τιμή αμέσως χωρίς να συλλέξει το παιδί.

  • Κλείσιμο σωλήνα με μη μηδενικό τερματισμό - η close επιστρέφει ψευδή τιμή και θέτει την $! σε 0, ώστε η έκφραση $! ? "$!" : "exit $?" να διακρίνει αποτυχία σε επίπεδο OS από κανονικό μη μηδενικό τερματισμό.

  • Κλειστό ή μη έγκυρο handle - το κλείσιμο handle που δεν είναι ανοιχτό θέτει την $! σε "Bad file descriptor" και επιστρέφει ψευδή τιμή. Υπό use warnings, εκπέμπεται προειδοποίηση close() on unopened filehandle.

  • STDIN / STDOUT / STDERR - μπορούν να κλείσουν όπως οποιοδήποτε άλλο handle. Ο περιγραφέας απελευθερώνεται και θα ξαναχρησιμοποιηθεί από την επόμενη open στο πρότυπο handle, στο οποίο βασίζεται η κλασική ανακατεύθυνση open STDOUT, ">", "log".

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

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

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

  • open - το αντίστροφο· μια open σε ήδη ανοιχτό handle εκτελεί πρώτα έμμεσο close (αλλά δεν μηδενίζει την $.)

  • print - η τελική ενταμιευμένη print εκκενώνεται μέσα στην close, οπότε η πραγματική επιτυχία της εγγραφής γίνεται γνωστή μόνο μετά την close

  • fileno - αριθμός περιγραφέα ενός handle· γίνεται μη έγκυρος μόλις πετύχει η close

  • binmode - η στοίβα στρωμάτων που έχει οριστεί από την binmode αποδομείται κατά τη διάρκεια της close, και η ίδια η αποδόμηση μπορεί να αποτύχει

  • $? - κατάσταση εξόδου του παιδιού που συμπληρώνεται από την close σε handle σωλήνα

  • $! - σφάλμα από την αποτυχημένη λειτουργία κλεισίματος