I/O#
Το filehandle είναι το όριο ανάμεσα στον κόσμο κειμένου του προγράμματός σας και στον έξω κόσμο των bytes. Το να κάνετε το Unicode σωστά σημαίνει να στήσετε αυτό το όριο σωστά κατά την open (ή με binmode), ώστε οι συνηθισμένες print και readline να μιλούν ήδη τη σωστή κωδικοποίηση.
Στρώματα PerlIO#
Κάθε filehandle φέρει μια στοίβα από layers - μικρά κομμάτια μηχανισμού που μετασχηματίζουν τα bytes καθώς διασχίζουν το όριο. Τα σχετικά για το Unicode είναι:
:raw- κανένας μετασχηματισμός. Bytes μέσα, bytes έξω.:utf8- ελέγχει ότι τα bytes που διαβάζονται σχηματίζουν έγκυρο UTF-8 και σημειώνει τη συμβολοσειρά ως κείμενο. Εμπιστεύεται τον χρήστη να μην παράγει μη έγκυρο UTF-8 στις εγγραφές.:encoding(ENCODING)- αποκωδικοποίηση κατά την ανάγνωση, κωδικοποίηση κατά την εγγραφή, για οποιαδήποτε ονομασμένη κωδικοποίηση. Απορρίπτει την κακοσχηματισμένη είσοδο εξ ορισμού.:crlf- μεταφράζει"\r\n"σε"\n"κατά την ανάγνωση,"\n"σε"\r\n"κατά την εγγραφή. Στο Linux αυτό είναι ανενεργό· στα Windows είναι η προεπιλογή για handles κειμένου.
Το :encoding(UTF-8) είναι αυτό που σχεδόν πάντα θέλετε. Προτιμήστε το από το σκέτο layer :utf8 - η μορφή :encoding(...) επικυρώνει, το :utf8 όχι.
Άνοιγμα ενός αρχείου με κωδικοποίηση#
Η μορφή τριών ορισμάτων της open παίρνει ένα mode που μπορεί να περιλαμβάνει layers:
open my $in, "<:encoding(UTF-8)", "input.txt" or die "open: $!";
open my $out, ">:encoding(UTF-8)", "output.txt" or die "open: $!";
while (my $line = <$in>) {
chomp $line; # characters, not bytes
print $out uc $line, "\n"; # encoded on the way out
}
Κάθε readline από το $in επιστρέφει μια συμβολοσειρά κειμένου. Κάθε print προς το $out κωδικοποιείται σε UTF-8 στο καλώδιο. Το σώμα του βρόχου βλέπει μόνο χαρακτήρες - καμία decode, καμία encode, καμία μέτρηση bytes κατά λάθος.
Εκ των υστέρων προσθήκη με binmode#
Αν το filehandle είναι ήδη ανοιχτό - για παράδειγμα οι standard streams, ή ένα handle που σας έδωσε ένα άλλο άρθρωμα - προσαρτήστε το layer με binmode:
binmode STDIN, ":encoding(UTF-8)";
binmode STDOUT, ":encoding(UTF-8)";
binmode STDERR, ":encoding(UTF-8)";
Κάντε το αυτό μία φορά, στην κορυφή του προγράμματος, πριν από οποιοδήποτε I/O σε αυτά τα handles. Μετά από αυτό τα standard streams συμπεριφέρονται όπως ένα αρχείο ανοιγμένο με ένα layer κωδικοποίησης.
Η pragma use open#
Το να γράφετε το ίδιο layer :encoding(UTF-8) σε κάθε open είναι θορυβώδες. Η pragma open ορίζει τα προεπιλεγμένα layers για όλα τα επόμενα ανοίγματα στην περικλείουσα εμβέλεια:
use open ":std", ":encoding(UTF-8)";
Η ετικέτα :std επίσης ξανα-στρώνει τα STDIN, STDOUT και STDERR επιτόπου, οπότε παίρνετε το αποτέλεσμα τριών κλήσεων binmode και μια προεπιλογή για κάθε μεταγενέστερη open σε μία γραμμή.
Αυτό είναι το μονόγραμμο στην κορυφή ενός σύγχρονου σεναρίου με επίγνωση Unicode:
use utf8;
use open ":std", ":encoding(UTF-8)";
use utf8- οι κυριολεξίες σε αυτό το αρχείο πηγαίου κώδικα είναι UTF-8.use open ":std", ":encoding(UTF-8)"- τα stdin/stdout/stderr και κάθε μεταγενέστερο open έχουν προεπιλογή UTF-8 στο καλώδιο.
Μπορείτε επίσης να ωθήσετε το I/O σε UTF-8 από έξω από το πρόγραμμα με τη μεταβλητή περιβάλλοντος PERL_UNICODE. Τα γράμματα I, O, E επιλέγουν stdin, stdout και stderr μεμονωμένα, το S επιλέγει και τα τρία ταυτόχρονα με τον τρόπο που το κάνει η pragma use open ":std", και το A αποκωδικοποιεί το @ARGV, οπότε το PERL_UNICODE=SA είναι περίπου το ισοδύναμο γραμμής εντολών του δίγραμμου προλόγου παραπάνω. Για να αποκωδικοποιήσετε τα ορίσματα μέσα στο πρόγραμμα αντ” αυτού, γράψτε @ARGV = map { decode('UTF-8', $_, 1) } @ARGV.
Ο αντίστοιχος διακόπτης γραμμής εντολών -C (-CSA) δεν αναγνωρίζεται ακόμη από την pperl, που είναι μια απόκλιση από τη στάνταρ perl· χρησιμοποιήστε τη μεταβλητή PERL_UNICODE ή την pragma use open μέχρι να υλοποιηθεί.
Binary I/O παράλληλα με I/O κειμένου#
Κάποια handles φέρουν bytes, όχι κείμενο - αρχεία εικόνων, συμπιεσμένα streams, πρωτόκολλα δικτύου που πλαισιώνουν τη δική τους κωδικοποίηση. Ανοίξτε εκείνα :raw και μην προσαρτάτε ποτέ κωδικοποίηση:
open my $img, "<:raw", "photo.jpg" or die "open: $!";
Μέσα σε ένα πρόγραμμα, κάποια handles μπορεί να είναι κειμένου (:encoding(UTF-8)) και άλλα binary (:raw). Κρατήστε τις ετικέτες ξεκάθαρες: ένα binary handle σας δίνει συμβολοσειρές bytes, ένα handle κειμένου σας δίνει συμβολοσειρές κειμένου, και το $! είναι το ίδιο όπως και να “χει.
Διαδραστική είσοδος#
Ένα terminal δεν σας λέει σε ποια κωδικοποίηση πληκτρολογεί. Στο σύγχρονο Linux είναι σχεδόν πάντα UTF-8· στα Windows το προεπιλεγμένο code page της κονσόλας είναι ακόμη συχνά CP1252 ή CP437. Η συνήθης υπόθεση για διαπλατφορμικά σενάρια είναι UTF-8, με binmode εφαρμοσμένο κατά την εκκίνηση:
binmode STDIN, ":encoding(UTF-8)";
Αν το πρόγραμμά σας πρέπει να υποστηρίζει παλαιά terminals, αποκωδικοποιήστε με βάση τη μεταβλητή περιβάλλοντος LANG ή LC_CTYPE, ή αποδεχτείτε μια σημαία --encoding. Δεν υπάρχει φορητή αυτόματη ανίχνευση.
Έλεγχος των layers#
Για να δείτε ποια layers υπάρχουν σε ένα handle, χρησιμοποιήστε την PerlIO::get_layers:
use PerlIO;
my @layers = PerlIO::get_layers(\*STDOUT);
print "@layers\n"; # e.g. unix perlio encoding(utf-8-strict)
Χρήσιμο όταν ένα πρόγραμμα παράγει σιωπηλά διπλά-κωδικοποιημένη έξοδο και θέλετε να βρείτε ποιο handle έχει το απρόσμενο layer πάνω του.