Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading a file when someone writes to it

Tags:

perl

The script reads the lines from the file, here's the code:

#!/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;

If I add lines through cat, then the script reads the new lines. But if I edit the file through a vim editor, then the script does not see any new lines in the file and issues an EOF. Why does the script behave this way and do not see new lines?

Output of the script:

$ 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

The initial content of the input.txt:

row_1
row_2
row_3

Added via cat:

$ cat >> input.txt
row_4
row_5

Added via vim:

$ vim input.txt
row_6
row_7
like image 461
Dmitriy Avatar asked Sep 10 '18 19:09

Dmitriy


People also ask

Can you read a file while it's being written?

Most likely, you'll have to make your program open the file, read a small chunk, close the file, and then wait for a bit before reading again. Even then, there's no guarantee that you won't have the file open when the writing process tries to write.

How do I read data from a text file?

To read from a text fileUse the ReadAllText method of the My. Computer. FileSystem object to read the contents of a text file into a string, supplying the path. The following example reads the contents of test.

How do you open a file that says write and read it?

'r+' opens the file for both reading and writing. On Windows, 'b' appended to the mode opens the file in binary mode, so there are also modes like 'rb', 'wb', and 'r+b'. Also reading then writing works equally well using 'r+b' mode, but you have to use f. seek(0) between f.


1 Answers

The shell's >> directive opens the existing file, while vim creates a new file with the same name as the old one, leaving your program reading an a now-anonymous file.

$ 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

You need to re-open the file.

#!/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;

Outputs:

$ 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
like image 97
ikegami Avatar answered Oct 05 '22 01:10

ikegami