Strawberry perl 在写入 UTF-8 文件时给了我一个 "Wide character in print"
Strawberry perl gives me a "Wide character in print" when writing to a UTF-8 file
我是 运行 Strawberry perl 脚本,它读取文件并进行一些处理并将输出写入另一个文件。当它似乎在原始文件中遇到一些非 ASCII 字符(扩展)时,我有时会收到此消息。
Wide character in print at cv2pf.pl line 348, <$fh> chunk 1307
这意味着什么,我该如何解决?它似乎对输出文件没有任何影响,除非我遗漏了什么。
这里给出的解决方案:
不能解决问题。我正在将输出写入文件而不是控制台,因此该解决方案不起作用。
我在打开文件时指定了 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 文件打开。
File encoding: 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;
}
经过大量挖掘后发现错误是因为您使用 :encoding(utf8)
的显式模式显式打开文件句柄的哈希,然后立即将其更改为 unencoded 使用 binmode
以下内容对于任何 Perl 程序也非常重要
用 use strict
和 use 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 $/
临时对全局变量执行此操作,并使用代码块 { ... }
来限制更改范围
解决方案是 use open
使用适当的编码层。您正在写入文件而不是 STDOUT 的事实不会改变任何东西。
# 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");
我是 运行 Strawberry perl 脚本,它读取文件并进行一些处理并将输出写入另一个文件。当它似乎在原始文件中遇到一些非 ASCII 字符(扩展)时,我有时会收到此消息。
Wide character in print at cv2pf.pl line 348, <$fh> chunk 1307
这意味着什么,我该如何解决?它似乎对输出文件没有任何影响,除非我遗漏了什么。
这里给出的解决方案:
我在打开文件时指定了 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 文件打开。
File encoding: 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;
}
经过大量挖掘后发现错误是因为您使用 :encoding(utf8)
的显式模式显式打开文件句柄的哈希,然后立即将其更改为 unencoded 使用 binmode
以下内容对于任何 Perl 程序也非常重要
用
use strict
和use 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 $/
临时对全局变量执行此操作,并使用代码块{ ... }
来限制更改范围
解决方案是 use open
使用适当的编码层。您正在写入文件而不是 STDOUT 的事实不会改变任何东西。
# 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");