2013-02-25 108 views
3

我有一个编码为PC UTF-8的文件。我想将文件转换为PC ANSI。Perl - 将PC UTF-8转换为PC ANSI

我已经尝试了下面,但我总是得到输出文件为PC UTF-8。

use Encode; 

$infile = $ARGV[0]; 
open(INFILE, $infile); 

my $outfile = "temp.txt"; 

open(OUTFILE, ">$outfile"); 

while(<INFILE>) { 
    my $row = $_; 
    chomp $row; 

    $row = Encode::encode("Windows-1252", $row); 
    print OUTFILE $row."\n"; 

} 

close INFILE; 
close OUTFILE; 
+2

这是*略*浪费'chomp'行,然后追加'\ N'它。 – 2013-02-25 21:58:43

+1

你可以用一个*非常小的文件来试试它,比如用一个非ASCII字符表示一行,然后向我们展示一个输入和输出的十六进制转储? – 2013-02-25 22:07:12

+1

这与你的问题没有关系,但是'open'的3参数版本是首选。 http://modernperlbooks.com/mt/2010/04/three-arg-open-migrating-to-modern-perl.html – 2013-02-25 22:08:57

回答

9

的问题是,你永远不会解码您编码数据。

use strict; 
use warnings; 
use Encode qw(encode decode); 

open(my $INFILE, '<', $ARGV[0]) or die $!; 
open(my $OUTFILE, '>', $ARGV[1]) or die $!; 

while (my $utf8 = <$INFILE>) { 
    my $code_points = decode('UTF-8', $utf8); # <-- This was missing. 
    my $cp1252 = encode('cp1252', $code_points); 
    print $OUTFILE $cp1252; 
} 

但是你可以多一点很容易做到这一点:

use strict; 
use warnings; 

open(my $INFILE, '<:encoding(UTF-8)', $ARGV[0]) or die $!; 
open(my $OUTFILE, '>:encoding(cp1252)', $ARGV[1]) or die $!; 

while (<$INFILE>) { 
    print $OUTFILE $_; 
} 
+1

('cp1252'只是写'Windows-1252'的一种较短的方式) – ikegami 2013-02-25 23:30:56

+1

这似乎是有效的。我只是收到一条消息“”\ x {feff}“不映射到cp1252”。任何过滤这些的好方法? – user333746 2013-02-26 01:10:46

+1

您可以将第三个参数传递给'encode'来处理这些参数。 – ikegami 2013-02-26 01:27:18

1

而不是手动进行解码和编码,您应该使用PerlIO-Layers。您可以使用binmode功能指定层,还是在模式参数三ARG open

use strict; use warnings; 
use autodie; 

open my $INFILE, '<:utf8',     $ARGV[0]; 
open my $OUTFILE, '>:encoding(iso-8859-1)', "temp.txt"; 
#     ^-- the layers 

while (my $line = <$INFILE>) { 
    print $OUTFILE $line; 
} 

注意,Perl的默认情况下不打开文件UTF8,你必须指定解码层好。图层:encoding(utf8)非常常见,您可以直接说:utf8

可以列出所有可用的编码与

​​
+0

我在(eval 21)第109行得到一个异常“未知的PerlIO层”iso“。” ??? – user333746 2013-02-25 22:29:49

+0

@ user333746①检查可用编码列表,查看您当前安装的内容。 ②请将您的代码与我更新的帖子进行比较;图层是':encoding(foo-bar)'(我的初始文章有错误)。 ③你正在运行什么版本的Perl?为什么选择'eval' - 你在mod_perl下? – amon 2013-02-25 22:39:23

+1

为什么你从Windows-1252更改为iso-8859-1?他们不一样,OP明确表示他想要“ANSI”编码(这就是Windows所说的单字节本地编码,大多数机器上的Windows-1252又名cp1252,neve iso-8859-1) 。 – ikegami 2013-02-25 23:26:16