2010-07-24 60 views
0

我在Perl中遇到Unicode字符问题。当我从网上收到数据时,我经常会看到像√¢¬Ä¬ú√¢¬Ç¬¨这样的字符。第一个是引号,第二个是欧元符号。Perl Text :: CSV_XS编码问题

现在我可以很容易地用Perl中的正确值替换,并在屏幕上打印正确的单词,但是当我尝试输出到.CSV文件时,我所做的所有替换都是无用的, .CSV文件。 (引号工作,猜测,因为它是一个普通的字符)。 Numéro也会给Numéro。这些例子是无止境的。

我写了一个小程序来试图解决这个问题,但我不确定问题是什么。我读过另一个堆栈溢出线程,您可以在Excel中导入.CSV并选择UTF8编码,但该选项不会弹出给我。我想知道如果我可以将它编码到任何Excel的本地字符集(UTF16BE ???)中,或者是否有其他解决方案。我在这个简短的程序中尝试了很多变体,并且让我再说一次,它只是为了测试Unicode问题,而不是合法程序的一部分。谢谢。

use strict; 
use warnings; 
require Text::CSV_XS; 
use Encode qw/encode decode/; 

my $text = 'Numéro Numéro Numéro Orkos Capital SAS (√¢¬Ä¬úOrkos√¢¬Ä¬ù) 325M√¢¬Ç¬¨ in 40 companies headquartered'; 

print("$text\n\n\n"); 

$text =~ s/“|”/"/sig; 
$text =~ s/’s/'s/sig; 
$text =~ s/√¢¬Ç¬¨/€/sig; 
$text =~ s/√¢¬Ñ¬¢/®/sig; 
$text =~ s/ / /sig; 

print("$text\n\n\n"); 

my $CSV = Text::CSV_XS->new ({ binary => 1, eol => "\n" }) or die "Cannot use CSV: ".Text::CSV->error_diag(); 

open my $OUTPUT, ">:encoding(utf8)", "unicode.csv" or die "unicode.csv: $!"; 

my @row = ($text); 

$CSV->print($OUTPUT, \@row); 
$OUTPUT->autoflush(1); 

我也试过这两条线都无济于事:

$text = decode("Guess", $text); 
$text = encode("UTF-16BE", $text); 

回答

0

所以我想出了答案,来自Roland Illig的评论帮助我到达那里(再次感谢!)。解码不止一次会导致宽字符错误,因此不应该这样做。

这里的关键是解码UTF-8文本,然后在MacRoman中进行编码。要将.CSV文件发送给我的Windows用户,我必须首先将它保存为.XLSX,以便编码不会再受到任何影响。

 
$text =~ s/“|”/"/sig; 
$text =~ s/’s/'s/sig; 
$text =~ s/√¢¬Ç¬¨/€/sig; 
$text =~ s/√¢¬Ñ¬¢/®/sig; 
$text =~ s/ / /sig; 

$text = decode("UTF-8", $text); 

print("$text\n\n\n"); 

my $CSV = Text::CSV_XS->new ({ binary => 1, eol => "\n" }) or die "Cannot use CSV: ".Text::CSV->error_diag(); 

open my $OUTPUT, ">:encoding(MacRoman)", "unicode.csv" or die "unicode.csv: $!"; 
1

首先,你的字符串在MacRoman编码。当你将它们解释为字节序列时,第二个结果是C3 A2 C2 82 C2 AC。这看起来像UTF-8,解码后的形式是E2 82 AC。这再次看起来像UTF-8,当你解码它时,你会得到。所以你需要做的是:

$step1 = decode("MacRoman", $text); 
$step2 = decode("UTF-8", $step1); 
$step3 = decode("UTF-8", $step2); 

不要问我在哪个神秘的方式,这种编码已经在第一个地方创建。你的第一个字符解码为U+201C,这确实是LEFT DOUBLE QUOTATION MARK

注意:如果你在Mac上,第一个解码步骤可能是不必要的,因为编码只在“表示层”(当你将Perl源复制到HTML表单中,并且浏览器执行了编码 - 你的翻译)而不是数据本身。

+0

当我尝试这一点,我得到以下错误: 不能/Library/Perl/Updates/5.10.0/darwin-thread-multi-2level/Encode.pm线174解码字符串宽字符。 什么是“宽字符”?另外我在Mac上。 – user387049 2010-07-24 21:22:54

+0

通常,当你对某些东西进行解码时,你会从一个字节序列到一个字符序列。 “宽字符”错误消息告诉你,你已经有一个字符序列。这是一个安全网,阻止你做你通常不想做的事情。 – 2010-07-24 22:01:20

+0

如果你不是在MacRoman编码中保存你的Perl程序,而是在UTF-8中保存你的Perl程序,它可能会有所帮助。或者你已经这样做了? – 2010-07-24 22:03:10