Mám nasledujúci kód Perlu, v ktorom otváram popisovač skalárnej premennej a zapisujem do neho nejaký text utf8:
use warnings;
use strict;
use 5.010;
use utf8;
use open qw( :std :encoding(utf8) );
my $output;
open my $oh, ">", $output;
say $oh "Žluťoučký kůň.";
close $oh;
say "Žluťoučký kůň.";
print $output;
a keď ho spustím, dostanem nasledujúci výstup:
Žluťoučký kůň.
ŽluÅ¥ouÄký kůÅ.
(bez upozornení alebo chýb). Takže, samozrejme, písanie utf8 reťazca do premennej cez rukoväť tu nefunguje správne, pretože reťazec sa zdá byť dvojkódovaný. Snažil som sa otvoriť >:raw
, >:bytes
, >:encoding(ascii)
, ale nič z toho nepomohlo.
Možno som robil niečo hlúpe, ale nemôžem zistiť, ako to vyriešiť. Nejaké nápady?
odpovede:
7 pre odpoveď č. 1Po prvé, :encoding(utf8)
by mala byť :encoding(utf-8)
.
utf-8
je dobre známy štandard kódovania.utf8
je rozšírenie špecifické pre Perl k utf-8.
(Názvy kódovania nie sú citlivé na veľkosť písmen.)
use open qw( :std :encoding(utf8) );
má dva účinky:
- Dodáva
:encoding(utf8)
naSTDIN
,STDOUT
aSTDERR
. - Nastaví predvolenú vrstvu pre
open
v lexikálnom rozsahuuse
na:encoding(utf8)
.
takže,
use utf8;
use open qw( :std :encoding(utf-8) );
# String of decoded text aka string of Unicode Code Points, thanks to `use utf8`.
my $text_ucp = "Žluťoučký kůň.";
# $output will contain text encoded using utf-8 thanks to `use open`.
open my $oh, ">", my $text_utf8;
say $oh $text_ucp;
close $oh;
# ok. Will encode the decoded text using utf-8 thanks to `use open`.
say $text_ucp;
# XXX. Will encode the already-encoded text using utf-8 thanks to `use open`.
print $text_utf8;
Pokúsili ste sa potlačiť druhý efekt use open
Ak chcete získať súbor kódových bodov Unicode, ale to je zbytočné, pretože súbory môžu obsahovať iba bajty. Niektoré typy kódovania alebo zlyhania sa musia vyskytnúť, ak sa pokúsite uložiť do súboru niečo iné ako bajty.
Takže žiť s ním, a dekódovať "súbor" pred použitím.
use utf8;
use open qw( :std :encoding(utf-8) );
use Encode qw( decode_utf8 );
my $text_ucp = "Žluťoučký kůň.";
open my $oh, ">", my $text_utf8;
say $oh $text_ucp;
close $oh;
my $text2_ucp = decode_utf8($text_utf8);
... Do stuff with $text_ucp and/or $text2_ucp ...
say $text_ucp;
say $text2_ucp;
Je možné sa tomu vyhnúť decode
priamo v utf-8 v druhej polovici programu.
use utf8;
BEGIN { binmode(STDERR, ":encoding(utf-8)"); } # We"ll handle STDOUT manually.
use open qw( :encoding(utf-8) );
use Encode qw( encode_utf8 );
my $text_ucp = "Žluťoučký kůň.";
open my $oh, ">", my $text_utf8;
say $oh $text_ucp;
close $oh;
say encode_utf8($text_ucp);
say $text_utf8;
To samozrejme znamená, že nemôžete použiť $text_utf8
kdekoľvek, čo očakáva dekódovaný text.