Прочитайте UTF-8 в Perl и выведите как ISO-8859-1

Мне нужно прочитать текстовый файл в Perl, который закодирован как UTF-8, это работает нормально. Мой выходной файл OUT_2 должен быть закодирован как ISO-8859-1 (также известный как «Latin1»). Я пробовал этот код (и некоторые другие), но мой выходной файл OUT_2 всегда записывается как UTF-8. Любая идея для достижения этого?

use strict;
use Encode::Encoder;

open IN, "c:/Temp/Input.txt"; # this file is UTF-8

open OUT_1, ">", "c:/Temp/out_1.txt"; 
# encoding of OUT_1 does not matter because it contains only ASCII
open OUT_2, ">:encoding(latin1)", "c:/Temp/out_2.txt"; 

my $line = 1;
while ( <IN> ) {
    chomp;
    print OUT_1 "Write line $line\n";
    print OUT_2 "$_ and some stuff\n";
    $line++;
}

close IN;
close OUT_1;
close OUT_2;

Это предложение тоже не работает:

 my $data = "$_ and some stuff\n";
 Encode::encode("latin1", Encode::decode("UTF-8", $data));
 print OUT_2 $data;

person Wernfried Domscheit    schedule 10.12.2015    source источник
comment
Есть ли в вашем вводе символы, отличные от ASCII?   -  person Alastair McCormack    schedule 10.12.2015
comment
Да, но все соответствует ISO-8859-1   -  person Wernfried Domscheit    schedule 10.12.2015


Ответы (2)


Кажется, это работает правильно (см. описание Perl-функции open; нет необходимости для явного преобразования строки Perl на уровне октетов с помощью encode/decode) (дальше, возможно, см. описание open и binmode):

#!/usr/bin/perl

use strict;
use warnings;

open my $in,  '<:encoding(UTF-8)',  'input-file-name'  or die $!;
open my $out, '>:encoding(latin1)', 'output-file-name' or die $!;

while (<$in>) {
  print $out $_;
}

Единственное существенное отличие от вашего кода заключается в том, что я явно декодирую входящие данные из байтов UTF8 в символы.

Что вы делаете, чтобы узнать, каковы кодировки ваших входных и выходных файлов? Я использовал file.

$ file input-file-name output-file-name
input-file-name: UTF-8 Unicode text
output-file-name:  ISO-8859 text

А еще od -ch:

$ od -ch input-file-name
0000000   a   a   a 302 243 302 243 302 243   z   z   z  \n
           6161    c261    c2a3    c2a3    7aa3    7a7a    000a
0000015

$ od -ch output-file-name
0000000   a   a   a 243 243 243   z   z   z  \n
           6161    a361    a3a3    7a7a    0a7a
0000012

(Мой файл содержал «aaa£££zzz».)

person Dave Cross    schedule 10.12.2015
comment
Я никогда раньше не использовал Perl, поэтому мне интересно, где в вашем скрипте я должен указать имя файла, который я хочу преобразовать? - person zwlayer; 30.08.2017
comment
@zwlayer: я обновил свой ответ таким образом, чтобы (надеюсь) сделать его более понятным. - person Dave Cross; 30.08.2017
comment
Спасибо большое. Я понял. Надеюсь, однажды появится какой-нибудь парень и сделает интерпретатор для тех, кто хочет использовать фрагменты Perl, не зная даже, как читать Perl :) - person zwlayer; 30.08.2017
comment
@zwlayer: я очень надеюсь, что нет. Вы получаете гораздо лучшие программы, когда люди действительно тратят время на то, чтобы понять код, который они пишут :-) - person Dave Cross; 30.08.2017
comment
Я согласен с вами, когда PL - это не perl :) Бьюсь об заклад, perl не предназначен для чтения, а просто для записи. - person zwlayer; 30.08.2017
comment
@zwlayer: Ну, тут ты не прав. И добавление смайлика к несмешному комментарию волшебным образом не делает его смешным. - person Dave Cross; 30.08.2017
comment
Несмотря на то, что я не хочу превращать это в дискуссию, я считаю, что должен сказать, что маркировка утверждений некоторыми тегами, такими как смешные или несмешные, не является рациональной вещью, поскольку это субъективные категории. - person zwlayer; 30.08.2017

Я думаю, вы ищете Encode::encode($encoding_out, Encode::decode($encoding_in, $data));, где $encoding_in и $encoding_out в вашем случае будут UTF-8 и Latin1 (iso-8859-1) соответственно.

Если у вас есть непечатаемые символы в UTF-8, преобразование без потерь будет невозможно, учитывая, что набор возможных символов в UTF-8 больше, чем набор возможных символов в Latin-1. Любые символы, которые не переводятся, будут заменены знаком «?».

person femmestem    schedule 10.12.2015