当写入UTF-8文件时,草莓perl给我一个“宽字符打印”

时间:2017-07-02 05:09:21

标签: perl utf-8 strawberry-perl

我在Strawberry perl中运行一个脚本,它读取文件并进行一些处理并将输出写入另一个文件。我有时会在原始文件中遇到一些非ASCII字符(扩展名)时收到此消息。

Wide character in print at cv2pf.pl line 348, <$fh> chunk 1307

含义是什么,我该如何解决?它似乎对输出文件没有任何影响,除非我遗漏了什么。

这里给出的解决方案: Decode unicode escape characters with perl无法解决问题。我正在将输出写入文件而不是控制台,因此解决方案不起作用。

我在打开文件时指定了UTF-8,但它仍然给出了错误

# Detect the file type UTF-8 or not
if (!open(READ,$sourcefile))
{
    print "Error: Could not open $sourcefile for detecting.\n";
    next;
}
my $line = <READ>;
my $enc = Encode::Detect::Detector::detect($line);
print "File encoding: $enc\n";
close READ;

if ($enc eq "UTF-8")
{
    if (!open(READ,'<:encoding(UTF-8)',$sourcefile))
    {
        print "Error: Could not open UTF-8 $sourcefile for reading.\n";
        next;
    }
}
else
{
    if (!open(READ,$sourcefile))
    {
        print "Error: Could not open $sourcefile for reading.\n";
        next;
    }
}

if (!open($fh,"+>:encoding(utf8)","$base.m.csv"))
{
    print "Error: Could not open $base.m.csv for reading/writing.\n";
    next;
}

undef $/;
$_=<READ>;
# remove the BOM
if ($enc eq "UTF-8")
{
    $_ =~ s/\x{FEFF}//g;
}
# convert unix line ending to dos
$_ =~ s/\r?\n|\r/\r\n/g;
print $fh $_;
close READ;

$/ = "\r\n";
seek ($fh,0,0);

my $csv = Text::CSV->new ( { allow_whitespace => 1, binary => 1 } );  # should set binary attribute.

在输出中,我看到源文件是UTF-8,相应地被打开为UTF-8文件。

  

文件编码:UTF-8

我在这里缺少什么?

要求的其他代码:

第348行

print {$handles{$currency}} "P" . $row->{'Name'} . "\r\n";

my %handles;
curcheck: while ( $row = $csv->getline_hr( $fh ) ) {
    my $currency=$row->{'Currency'};
    if (exists $handles{$currency}) {
        next curcheck;
    }
    $handles{$currency}=return_fh();
    if (!open($handles{$currency},">:encoding(utf8)","$base-$currency.out"))
    {
        print "Error: Could not open $base-$currency.out for writing.\n";
        next file;
    }

    binmode($handles{$currency})
}
seek ($fh,0,0);
$row = $csv->getline ($fh);


...

sub return_fh {
    local *FH;
    return *FH;
}

2 个答案:

答案 0 :(得分:1)

经过大量挖掘后发现错误是因为您使用显式模式:encoding(utf8)显式打开文件句柄的哈希,然后立即将其更改为未编码 binmode

以下对于任何Perl程序都非常重要

  • 使用use strictuse warnings 'all'

  • 开始您的代码
  • 声明所有变量尽可能接近其第一个使用点;通常在定义时

  • 使用词汇文件句柄而不是全局句柄。例如

    unless ( open my $read, '<:encoding(UTF-8)', $sourcefile ) {
        print "Error: Could not open UTF-8 $sourcefile for reading.\n";
        next;
    }
    

    它们作为子程序参数传递要简单得多。并且Perl将在超出范围时自动关闭

  • 使用$var = undef代替undef $var将变量设置为undef。并使用local $/暂时对全局变量执行此操作,并使用代码块{ ... }来限制更改的范围

答案 1 :(得分:-1)

解决方案是# Add encoding layer to STD* use Win32 qw( ); use open ':std', ':encoding(cp'.Win32::GetConsoleOutputCP().')'; # Set default encoding layer for files open in scope of this. use open ':encoding(UTF-8)'; open(my $fh, '>', $qfn) or die("Can't create \"$qfn\": $!\n"); ,具有适当的编码层。您正在写入文件而不是STDOUT的事实不会改变任何内容。

urlConnection.setRequestMethod("POST");