我写了两个程序。一个程序将内容同时写入文本文件。另一个程序同时读取该内容。
但是这两个程序应该同时运行。对我来说,程序是正确写入文件。但是另一个程序没有读取文件。
我知道一旦写入过程完成,只有数据将存储在硬盘中。然后另一个进程可以读取数据。
但我希望在单个文件中同时读写不同的进程。我怎样才能做到这一点?
请帮帮我。 以下代码在文件中写入内容
sub generate_random_string
{
my $length_of_randomstring=shift;# the length of
# the random string to generate
my @chars=('a'..'z','A'..'Z','0'..'9','_');
my $random_string;
foreach (1..$length_of_randomstring)
{
# rand @chars will generate a random
# number between 0 and scalar @chars
$random_string.=$chars[rand @chars];
}
return $random_string;
}
#Generate the random string
open (FH,">>file.txt")or die "Can't Open";
while(1)
{
my $random_string=&generate_random_string(20);
sleep(1);
#print $random_string."\n";
print FH $random_string."\n";
}
以下代码是阅读内容的。这是另一个过程
open (FH,"<file.txt") or die "Can't Open";
print "Open the file Successfully\n\n";
while(<FH>)
{
print "$_\n";
}
答案 0 :(得分:4)
您可以使用精心设计的合作协议,如下所示。两端reader
和writer
都使用TakeTurns
模块中的公共代码来处理繁琐的细节,例如锁定和锁定文件所在的位置。客户只需要具有对文件的独占访问权限即可指定他们想要做的事情。
<强>读取器强>
#! /usr/bin/perl
use warnings;
use strict;
use TakeTurns;
my $runs = 0;
reader "file.txt" =>
sub {
my($fh) = @_;
my @lines = <$fh>;
print map "got: $_", @lines;
++$runs <= 10;
};
<强>作家强>
#! /usr/bin/perl
use warnings;
use strict;
use TakeTurns;
my $n = 10;
my @chars = ('a'..'z','A'..'Z','0'..'9','_');
writer "file.txt" =>
sub { my($fh) = @_;
print $fh join("" => map $chars[rand @chars], 1..$n), "\n"
or warn "$0: print: $!";
};
TakeTurns
模块工作时为execute-around:
package TakeTurns;
use warnings;
use strict;
use Exporter 'import';
use Fcntl qw/ :DEFAULT :flock /;
our @EXPORT = qw/ reader writer /;
my $LOCKFILE = "/tmp/taketurns.lock";
sub _loop ($&) {
my($path,$action) = @_;
while (1) {
sysopen my $lock, $LOCKFILE, O_RDWR|O_CREAT
or die "sysopen: $!";
flock $lock, LOCK_EX or die "flock: $!";
my $continue = $action->();
close $lock or die "close: $!";
return unless $continue;
sleep 0;
}
}
sub writer {
my($path,$w) = @_;
_loop $path =>
sub {
open my $fh, ">", $path or die "open $path: $!";
my $continue = $w->($fh);
close $fh or die "close $path: $!";
$continue;
};
}
sub reader {
my($path,$r) = @_;
_loop $path =>
sub {
open my $fh, "<", $path or die "open $path: $!";
my $continue = $r->($fh);
close $fh or die "close $path: $!";
$continue;
};
}
1;
示例输出:
got: 1Upem0iSfY got: qAALqegWS5 got: 88RayL3XZw got: NRB7POLdu6 got: IfqC8XeWN6 got: mgeA6sNEpY got: 2TeiF5sDqy got: S2ksYEkXsJ got: zToPYkGPJ5 got: 6VXu6ut1Tq got: ex0wYvp9Y8
即使你遇到这么多麻烦,仍然存在问题。该协议不可靠,因此reader
无法保证看到writer
发送的所有消息。如果没有writer
有效,则reader
会反复阅读相同的消息。
你可以添加所有这些,但更合理的方法是使用操作系统提供的抽象。
例如,Unix named pipes似乎与您想要的非常接近,并注意代码的简单性:
<强> PREAD 强>
#! /usr/bin/perl
use warnings;
use strict;
my $pipe = "/tmp/mypipe";
system "mknod $pipe p 2>/dev/null";
open my $fh, "<", $pipe or die "$0: open $pipe: $!";
while (<$fh>) {
print "got: $_";
sleep 0;
}
<强> PWRITE 强>
#! /usr/bin/perl
use warnings;
use strict;
my $pipe = "/tmp/mypipe";
system "mknod $pipe p 2>/dev/null";
open my $fh, ">", $pipe or die "$0: open $pipe: $!";
my $n = 10;
my @chars = ('a'..'z','A'..'Z','0'..'9','_');
while (1) {
print $fh join("" => map $chars[rand @chars], 1..$n), "\n"
or warn "$0: print: $!";
}
两端都尝试使用mknod
创建管道,因为它们没有其他同步方法。至少有一个会失败,但只要管道存在,我们就不在乎。
如您所见,所有等待的机器都由系统处理,因此您可以做您关心的事情:阅读和写信息。
答案 1 :(得分:3)
这很有效。
作者:
use IO::File ();
sub generate_random_string {...}; # same as above
my $file_name = 'file.txt';
my $handle = IO::File->new($file_name, 'a');
die "Could not append to $file_name: $!" unless $handle;
$handle->autoflush(1);
while (1) {
$handle->say(generate_random_string(20));
}
读者:
use IO::File qw();
my $file_name = 'file.txt';
my $handle = IO::File->new($file_name, 'r');
die "Could not read $file_name: $!" unless $handle;
STDOUT->autoflush(1);
while (defined (my $line = $handle->getline)) {
STDOUT->print($line);
}
答案 2 :(得分:-1)
另一个选项是内存映射文件。