Какой самый устойчивый к ошибкам способ чтения строки из CSV в хэш в Perl? - PullRequest
2 голосов
/ 13 марта 2012

Я думаю, что я, вероятно, здесь упускаю что-то очевидное, поэтому, пожалуйста, просветите меня.

В настоящее время я читаю файл CSV в perl, используя Text :: CSV, и это метод 'parse' (обрисован в общих чертах ниже).

csv-> метод разбора:

while (<FILE>) {
  if ($csv->parse($_)) {
     my @columns = $csv->fields();
     'refer to items with: $columns[1]'
  }
  else {
     'Handle the parse error here'
  }
}

Сейчас я ищу способ прочитать эти значения в хэш вместо массива. Просматривая документацию Text :: CSV, кажется, что наиболее эффективный способ сделать это - использовать метод 'getline' (обрисован в общих чертах ниже), но я не уверен, как отлавливать ошибки аналогично тому, как они отлавливаются с помощью подход массива.

csv-> getline метод:

my @cols = ("col1", "col2", "col3");
my $item = {};
$csv->bind_columns( \@{$item}{@cols} );
while( $csv->getline($it_fh) ) {
  'refer to items using: $item->{col1}'
}

Любые подсказки / советы / ссылки были бы хороши, так как мой Google, кажется, вышел пустым?

РЕДАКТИРОВАТЬ: Итак, вот мое понимание ответа, который я принял, просто чтобы прояснить то, что я понимаю как отказоустойчивость этого метода.

$csv->column_names( qw(col1 col2 col3) );
my $line;
until ( eof(FILE) ) {
    $line++;
    my $item = $csv->getline_hr( \*FILE );
    if ( $item ) {
        # refer to items as $item->{col1}
    } else {
        my $err = "Line: " . $line . "failed to parse\n"
        . "Input: " . $csv->error_input . "\n"
        . "Error: " . $csv->error_diag . "\n";
        print STDERR $err;
    }
}

Ответы [ 3 ]

2 голосов
/ 13 марта 2012

Ну, всегда есть простой подход:

my @cols = qw(col1 col2 col3);

while ( <FILE> ) {
   if ( $csv->parse($_) ) {
       my %item;
       @item{@cols} = $csv->fields();
       # refer to items using $item{col1}
   }
   else {
       # handle the parse error here
   }
}

Однако я подозреваю, что следующее может быть немного более эффективным, по крайней мере, если используется реализация Text :: CSV в XS:

$csv->column_names( qw(col1 col2 col3) );

until ( eof(FILE) ) {
    my $item = $csv->getline_hr( \*FILE );
    if ( $item ) {
        # refer to items as $item->{col1}
    } else {
        # handle the parse error here
    }
}
1 голос
/ 13 марта 2012

Правильное использование Text :: CSV_XS равно

use Text::CSV_XS qw( );

my $csv = Text::CSV_XS->new({ binary => 1 });

open my $fh, "<:encoding(UTF-8)", $qfn)
   or die("Can't open \"$qfn\": $!\n");

$csv->column_names(qw( col1 col2 col3 ));

while (my $row = $csv->getline_hr($fh)) {
  ...
}

$csv->eof()
   or die("CSV error processing \"$qfn\": ".($csv->error_diag())."\n");

Ранее опубликованная версия скрывала ошибки без всякой выгоды.

Если файл CSV имеет строку заголовка, вы можете использовать следующее:

my $header = $csv->getline($fh)
   or die("No header\n");
$csv->column_names(@$header);
0 голосов
/ 13 марта 2012

Вы хотите Текст :: CSV :: Slurp . Из его документов:

 use Text::CSV::Slurp;

 my $data = Text::CSV::Slurp->load(file       => $filename   [,%options]);
 my $data = Text::CSV::Slurp->load(filehandle => $filehandle [,%options]);
 my $data = Text::CSV::Slurp->load(string     => $string     [,%options]);

$ data теперь является массивом хеш-ссылок.

Редактировать: я упустил, что вопрос, вероятно, заключается в обработке ошибок. Я не думаю, что он выполняет какую-либо дополнительную проверку из коробки.

...