Чтение файла, когда кто-то пишет в него - PullRequest
0 голосов
/ 10 сентября 2018

Скрипт читает строки из файла, вот код:

#!/usr/bin/perl
use strict;
use warnings;
use AnyEvent;

open my $fh, '<', 'input.txt' or die "Can't open file: $!";

my $cv = AE::cv;

my $timer = AE::timer 0, 10, sub {
    printf "TELL: %s EOF: %s\n", tell $fh, eof $fh;
    print while <$fh>;
};

$cv->recv;

Если я добавляю строки через cat, тогда скрипт читает новые строки. Но если я отредактирую файл через редактор vim, тогда скрипт не увидит никаких новых строк в файле и выдаст EOF. Почему скрипт так себя ведет и не видит новых строк?

Вывод скрипта:

$ perl test.pl
TELL: 0 EOF:
row_1
row_2
row_3
TELL: 18 EOF: 1
TELL: 18 EOF: 1
TELL: 18 EOF:
row_4
TELL: 24 EOF:
row_5
TELL: 30 EOF: 1
TELL: 30 EOF: 1
TELL: 30 EOF: 1
TELL: 30 EOF: 1

Исходное содержимое файла input.txt:

row_1
row_2
row_3

Добавлено через кошку:

$ cat >> input.txt
row_4
row_5

Добавлено через vim:

$ vim input.txt
row_6
row_7

1 Ответ

0 голосов
/ 10 сентября 2018

Директива оболочки >> открывает существующий файл, в то время как vim создает новый файл с тем же именем, что и старое, в результате чего ваша программа читает теперь анонимный файл.

$ touch a

$ perl -MFile::stat -e'my $qfn = $ARGV[0]; my $s = stat($qfn) or die $!; printf "%s:%s\n", $s->dev, $s->ino' a
2065:1084527165

$ cat >>a
foo

$ perl -MFile::stat -e'my $qfn = $ARGV[0]; my $s = stat($qfn) or die $!; printf "%s:%s\n", $s->dev, $s->ino' a
2065:1084527165

$ vim a

$ perl -MFile::stat -e'my $qfn = $ARGV[0]; my $s = stat($qfn) or die $!; printf "%s:%s\n", $s->dev, $s->ino' a
2065:1084520254

Вам необходимо заново открыть файл.

#!/usr/bin/perl
use strict;
use warnings;
use AnyEvent;
use Fcntl qw( SEEK_SET );

my $cv = AE::cv;

my $qfn = $ARGV[0];
my $last_pos = 0;

my $timer = AE::timer 0, 10, sub {
    open(my $fh, '<', $qfn)
        or die("Can't open file: $!\n");
    seek($fh, $last_pos, SEEK_SET)
        or die("Can't seek: $!\n");

    printf "TELL: %s EOF: %s\n", tell $fh, eof $fh;

    print while <$fh>;

    ( $last_pos = tell($fh) ) >= 0
        or die("Can't tell: $!\n");
};

$cv->recv;

Выходы:

$ echo foo >a

$ perl a.pl a
TELL: 0 EOF:
foo
TELL: 4 EOF: 1
TELL: 4 EOF: 1        echo bar >>foo
TELL: 4 EOF:
bar
TELL: 8 EOF: 1
TELL: 8 EOF: 1        Used vim to change the file to "The quick brown fox"
TELL: 8 EOF:
k brown fox
TELL: 20 EOF: 1
^C
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...