0

我使用 perl 脚本从另一台服务器下载 CSV 文件。下载后我想检查文件是否包含任何损坏的数据。我尝试使用 Encode::Detect::Detector 来检测编码,但它在两种情况下都返回“undef”:

  1. 如果字符串是 ASCII 或
  2. 如果字符串损坏

所以使用下面的程序我无法区分 ASCII 和损坏的数据。

 use strict;
 use Text::CSV;
 use Encode::Detect::Detector;
 use XML::Simple;
 use Encode;
 require Encode::Detect;

 my @rows;
 my $init_file = "new-data-jp-2013-8-8.csv";



 my $csv = Text::CSV->new ( { binary => 1 } )
                 or die "Cannot use CSV: ".Text::CSV->error_diag ();

 open my $fh, $init_file or die $init_file.": $!";

 while ( my $row = $csv->getline( $fh ) ) {
     my @fields = @$row; # get line into array
     for (my $i=1; $i<=23; $i++){  # I already know that CSV file has 23 columns
            if ((Encode::Detect::Detector::detect($fields[$i-1])) eq undef){
                print "the encoding is undef in col".$i.
                            "  where field is ".$fields[$i-1].
                            " and its length is  ".length($fields[$i-1])." \n";
            }
            else {
            my $string = decode("Detect", $fields[$i-1]);
            print "this is string print  ".$string.
                    " the encoding is ".Encode::Detect::Detector::detect($fields[$i-1]).
                    " and its length is  ".length($fields[$i-1])."\n";
            }
        }   
     }
4

1 回答 1

1

您对编码有一些错误的假设,并且脚本中有一些错误。

foo() eq undef

没有任何意义。您不能将字符串相等性与 进行比较undef,因为undef它不是字符串。但是,它确实会字符串化为空字符串。当你做这样的垃圾时,你应该use warnings得到错误消息。要测试一个值是否不是undef,请使用defined

unless(defined foo()) { .... }

Encode::Detector::Detect模块使用面向对象的接口。所以,

Encode::Detect::Detector::detect($foo)

。根据文档,您应该这样做

Encode::Detect::Detector->detect($foo)

您可能无法逐个字段进行解码。通常,一个文档具有一种编码。打开文件句柄时需要指定编码,例如

use autodie;
open my $fh, "<:utf8", $init_file;

虽然 CSV 可以支持某种程度的二进制数据(如编码文本),但它不太适合此目的,您可能需要选择另一种数据格式。

最后,ASCII 数据实际上不需要任何解或编码。编码检测的undef结果在这里确实有意义。不能肯定地断言文档被编码为 ASCII(因为许多编码是 ASCII 的超集),但是给定某个文档,可以断言它不是有效的 ASCII(即设置了第 8 位)但必须而是更复杂的编码,如 Latin-1、UTF-8。

于 2013-09-20T09:02:42.817 回答