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, οπότε η πραγματική επιτυχία της εγγραφής γίνεται γνωστή μόνο μετά τηνclosefileno- αριθμός περιγραφέα ενός handle· γίνεται μη έγκυρος μόλις πετύχει ηclosebinmode- η στοίβα στρωμάτων που έχει οριστεί από τηνbinmodeαποδομείται κατά τη διάρκεια τηςclose, και η ίδια η αποδόμηση μπορεί να αποτύχει$?- κατάσταση εξόδου του παιδιού που συμπληρώνεται από τηνcloseσε handle σωλήνα$!- σφάλμα από την αποτυχημένη λειτουργία κλεισίματος