【发布时间】:2015-01-25 17:42:00
【问题描述】:
我有以下问题。我有一个来自外部源的 CSV 文件,我正在尝试通过以下方式使用 Text::CSV 模块读取它
$csv = Text::CSV->new({binary => 1}) or die "Could not open $filename : ".Text::CSV->error_diag();
binmode("stdout", ":utf8");
open $fh, "<encoding(utf8)", $filename or die "Could not open $filename : $!\n";
while ($row = $csv->getline($fh)) {
for ($i = 0; $i <= $#{$row}; $i++) {
$data = encode("utf8", $row->[$i]);
print "$data\n";
}
print "$row->[$keycol] => $row->[$valcol]\n";
$hash{$row->[$keycol]} = $row->[$valcol];
}
$csv->eof() or die " Error--- $i ".($csv->error_diag())."\n";
但是,在从该文件中读取几行后,程序因错误而死。
经过检查,我发现数据中有一些列应该用引号括起来 " ... " 但只有一个引号。那里没有匹配的引号,而是这个奇怪的 ^@ 字符。如何用引号替换所有这些 ^@ 字符?这不是简单的 ASCII 所以我不能做$str =~ s/\^\@/\"/g。
【问题讨论】:
-
什么是
$keycol?它没有在您显示的代码中定义。 -
你必须总是
use strict和use warnings在你编写的每个 Perl 程序的顶部,并尽可能使用my声明所有变量到他们的第一个使用点。 -
你说,“程序因错误而死”。请问错误信息是什么?你用什么来查看
^@字符?最有可能使用代码点为零来指示 NUL 字符。您的输入数据来自哪里?我认为如果数据确实包含不匹配的引号,您应该非常小心:很可能还有其他您没有注意到的问题。 -
Control-@也称为空字节
'\0',用于终止字符串。这是根据@(64)的ASCII值,对比A(65)的ASCII值,而^A(control-A)就是'\1,所以^@就是'\0'.在将数据作为字符串处理时,这会给您带来潜在的问题——^@标记了字符串的结尾。 -
感谢大家的指点。这确实看起来像一个数据问题,最好从数据的发送方解决,从接收方的角度来看似乎没有什么可做的。