LINUX.ORG.RU

Запись в CSV на perl

 ,


0

1

Для работы с CSV использую модуль Tie::Handle::CSV. Читается все нормально, а вот изменять поля в файле не получается. Вроде все делаю как в документации к модулю написано. Подскажите, пожалуйста, в чем может быть проблема.

Код:

#!/usr/bin/perl -w

use POSIX;
use strict;
use warnings;
use Tie::Handle::CSV;

my $csv_fh = Tie::Handle::CSV->new("test.csv", open_mode => '+<', sep_char => ';');
while (my $csv_line = <$csv_fh>)
{
    print $csv_line->{'name'}."\n";
    $csv_line->{'status'} = "done";
}
close $csv_fh;

Содержимое тестового файла CSV:

name;ip;status;serial
a;10.0.109.6;;
b;10.0.19.6;;
c;10.0.19.6;;
d;10.0.19.6;;
e;10.0.43.6;;

Результат выполнения:

$ cat test.csv 
name;ip;status;serial
a;10.0.109.6;;
b;10.0.19.6;;
c;10.0.19.6;;
d;10.0.19.6;;
e;10.0.43.6;;
$ ./test.pl 
a
b
c
d
e
$ cat test.csv 
name;ip;status;serial
a;10.0.109.6;;
b;10.0.19.6;;
c;10.0.19.6;;
d;10.0.19.6;;
e;10.0.43.6;;


Насколько помню Text::CSV_XS (тот что юзает твой Tie::Handle::CSV) не приучен писать файлы. Вообще. Автор запутал народ выставлением способом открытия файла. Пиши постаринке (seek, write, etc).

gh0stwizard ★★★★★
()

Так делать нельзя: текстовые файлы, которые представляют собой всего лишь линейную последовательность байт, слишком сложно обновлять на лету (по сути, их приходится переписывать целиком ради одной строки, если её длина при этом изменяется).

Tie::File мог бы быть решением, но и он неработоспособен на больших файлах.

Решение: по мере обработки данных пишите в файл test.csv.new, а потом делайте rename "test.csv.new", "test.csv". Благо, объекты Tie::Handle::CSV::Hash автоматически строкофицируются в валидный CSV.

AITap ★★★★★
()
Ответ на: комментарий от AITap

Ого. Не думал что так все обернется. У меня на этом Tie::Handle::CSV уже достаточно большой скрипт написан. И тут вдруг понадобилось мне еще и записывать в файл...

Спасибо! Буду ковырять дальше.

rayven
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.