在 Perl 中读取 UTF-8 并输出为 ISO-8859-1

Read UTF-8 in Perl and output as ISO-8859-1

我必须读取编码为 UTF-8 的 Perl 文本文件,它工作正常。我的输出文件 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;

我认为您正在寻找 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 中可能的字符集。任何不翻译的字符都将替换为“?”。

这似乎工作正常(参见 Perl 的 open function; there is no need to explicitly transform the Perl string on the octet level using encode/decode) (further afield, possibly see the description of the open pragma and the 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"。)