Как я могу преобразовать входной файл в кодировку UTF-8 в Perl? - PullRequest
7 голосов
/ 23 октября 2009

Я уже знаю, как преобразовывать не-utf8-кодированное содержимое файла строка за строкой в ​​кодировку UTF-8, используя что-то вроде следующего кода:

# outfile.txt is in GB-2312 encode    
open my $filter,"<",'c:/outfile.txt'; 

while(<$filter>){
#convert each line of outfile.txt to UTF-8 encoding   
    $_ = Encode::decode("gb2312", $_); 
...}

Но я думаю, что Perl может напрямую кодировать весь входной файл в формат UTF-8, поэтому я попробовал что-то вроде

#outfile.txt is in GB-2312 encode
open my $filter,"<:utf8",'c:/outfile.txt'; 

(Perl говорит, что что-то вроде "utf8" \ xD4 "не отображается на Unicode")

и

open my $filter,"<",'c:/outfile.txt'; 
$filter = Encode::decode("gb2312", $filter); 

(Perl говорит "readline () на неоткрытом дескрипторе файла!)

Они не работают. Но есть ли способ напрямую преобразовать входной файл в кодировку UTF-8?

Обновление:

Похоже, все не так просто, как я думал. Теперь я могу конвертировать входной файл в код UTF-8 окольным путем. Сначала я открываю входной файл и затем кодирую его содержимое в UTF-8, затем выводу в новый файл и затем открываю новый файл для дальнейшей обработки. Это код:

open my $filter,'<:encoding(gb2312)','c:/outfile.txt'; 
open my $filter_new, '+>:utf8', 'c:/outfile_new.txt'; 
print $filter_new $_ while <$filter>; 
while (<$filter_new>){
...
} 

Но это слишком много работы и это еще более хлопотно, чем просто кодировать содержимое $ filter построчно.

Ответы [ 2 ]

5 голосов
/ 23 октября 2009

Я думаю, что неправильно понял ваш вопрос. Я думаю, что вы хотите сделать, это прочитать файл в кодировке не-UTF-8, а затем поиграть с данными как UTF-8 в вашей программе. Это намного проще. После того, как вы прочитали данные с правильной кодировкой, Perl представляет их внутренне как UTF-8. Так что просто делай то, что должен.

Когда вы записываете его обратно, используйте любую кодировку, в которой вы хотите его сохранить. Однако вам не нужно помещать его обратно в файл, чтобы использовать его.


старый ответ

Слои ввода / вывода Perl считывают данные только при условии, что они уже правильно закодированы. Он не собирается конвертировать кодировку для вас. Говоря open для использования utf8, вы говорите, что это уже utf8.

Вы должны использовать модуль Encode так, как вы показали (если только вы не хотите написать свой собственный слой ввода / вывода). Вы можете конвертировать байты в UTF-8 или, если вы знаете кодировку, вы можете конвертировать из одной кодировки в другую. Поскольку, похоже, вы уже знаете кодировку, вам может потребоваться функция from_to().

Если вы только начинаете с Perl и Unicode, прежде чем что-либо делать, пройдите Советы по Unicode для Perl Джерда .

4 голосов
/ 23 октября 2009

Уровень: encoding вернет UTF-8, подходящий для использования в perl. То есть perl будет распознавать каждый символ как символ, даже если он состоит из нескольких байтов. В зависимости от того, что вы собираетесь делать дальше с данными, этого может быть достаточно.

Но если вы что-то делаете с данными, когда perl попытается понизить их с utf8, вам нужно либо указать perl не (например, делать binmode (STDOUT, ": utf8"), чтобы сообщить perl этот вывод значение stdout должно быть utf8), или вам нужно, чтобы perl рассматривал ваш utf8 как двоичные данные (интерпретируя каждый байт отдельно и ничего не зная о символах utf8.)

Для этого все, что вам нужно, это применить дополнительный слой к вашему открытию:

open my $foo, "<:encoding(gb2312):bytes", ...;

Обратите внимание, что выходные данные будут такими же:

perl -we'open my $foo, "<:encoding(gb2312):bytes", "foo"; $bar = <$foo>; print $bar'
perl -CO -we'open my $foo, "<:encoding(gb2312)", "foo"; $bar = <$foo>; print $bar'

, но в одном случае perl знает, что для чтения данных используется utf8 (и поэтому length ($ bar) сообщит о количестве символов utf8), и ему нужно явно указать (посредством -CO), что STDOUT примет utf8, и в другой, perl не делает никаких предположений о данных (и поэтому length ($ bar) сообщит о количестве байтов), и просто распечатывает их как есть.

...