2013-02-25 106 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