如何读取不断更新的文件?

时间:2009-09-15 05:13:02

标签: perl

我从外部服务器获取数据流(文本格式),并希望逐行将其传递给脚本。该文件以连续方式附加。哪个是执行此操作的理想方法。使用Perl的IO :: Socket方法会做什么?最终,这些数据必须通过PHP程序(可重用)并最终登陆MySQL数据库。

问题是如何打开文件,不断更新?

6 个答案:

答案 0 :(得分:24)

在Perl中,您可以使用seektell来读取不断增长的文件。它可能看起来像这样(从perldoc -f seek大量借用)

open(FH,'<',$the_file) || handle_error();  # typical open call
for (;;) {
    while (<FH>) {
        # ... process $_ and do something with it ...
    }
    # eof reached on FH, but wait a second and maybe there will be more output
    sleep 1;
    seek FH, 0, 1;      # this clears the eof flag on FH
}

答案 1 :(得分:9)

在perl中有几个模块可以更轻松地拖尾文件。 IO::TailFile::Tail一个使用回调,另一个使用阻塞读取,因此它取决于哪个更适合您的需求。可能还有其他拖尾模块,但这些是我想到的两个。

IO::Tail - 按照文件/流的尾部

 use IO::Tail;
 my $tail = IO::Tail->new();
 $tail->add('test.log', \&callback);
 $tail->check();
 $tail->loop();

File::Tail - 用于从不断更新的文件中读取的Perl扩展

use File::Tail;
my $file = File::Tail->new("/some/log/file");
while (defined(my $line= $file->read)) {
    print $line;
}

答案 2 :(得分:2)

也许named pipe可以帮到你?

答案 3 :(得分:1)

您谈论打开文件,并询问IO::Socket。这些并不是完全相同的东西,即使在内心深处你将要读取文件描述符的数据。

如果可以从命名管道或FIFO访问远程流,则可以将其作为普通文件打开。当没有任何可用时它将阻塞,并在有数据需要耗尽时返回。如果发件人跑得太远,你可能会,或者可能不需要File::Tail来解决不丢失数据的问题。

另一方面,如果你直接打开另一台服务器的套接字(似乎更有可能),IO::Socket开箱即用,因为没有getline方法可用。您必须逐块读取和缓冲,然后通过中间握笔逐行进行填充。

您可以将套接字描述符拉出到IO::Handle,然后使用getline()。类似的东西:

my $sock = IO::Socket::INET->new(
    PeerAddr => '172.0.0.1',
    PeerPort => 1337,
    Proto    => 'tcp'
) or die $!;

my $io = new IO::Handle;
$io->fdopen(fileno($sock),"r") or die $!;

while (defined( my $data = $io->getline() )) {
    chomp $data;
    # do something
}

您可能必须执行握手才能开始接收数据包,但这是另一回事。

答案 4 :(得分:0)

在python中它很简单:

f = open('teste.txt', 'r')
for line in f: # read all lines already in the file
    print line.strip()

# keep waiting forever for more lines.
while True:
    line = f.readline() # just read more
    if line: # if you got something...
        print 'got data:', line.strip()
    time.sleep(1) # wait a second to not fry the CPU needlessy

答案 5 :(得分:0)

阅读全部罚款以寻求最终的解决方案是性能不明智的。如果在Linux下发生这种情况,我建议只重命名日志文件。然后,您可以扫描重命名文件中的所有entite,而原始文件中的那些将再次填充。扫描完所有重命名的文件后 - 删除它。或者随心所欲地移动。通过这种方式,您可以获得类似logrotate的内容,但可以扫描新到达的数据。