2010-05-11 2 views
5

Я написал две программы. Одна программа одновременно записывает содержимое в текстовый файл. Другая программа читает этот контент одновременно.Чтение и запись в том же файле с другим процессом

Но обе программы должны работать в одно и то же время. Для меня программа записывает файл правильно. Но другая программа не читает файл.

Я знаю, что как только процесс записи будет завершен, а только данные будут сохранены на жестком диске. Затем другой процесс может считывать данные.

Но я хочу, чтобы как чтение, так и запись в одно и то же время в одном файле. Как я могу это сделать?

Пожалуйста, помогите мне. Следующий код записать содержимое в файле

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"; 
       } 
+1

Что вы еще пробовали. Не могли бы вы поделиться тем, что вы пробовали? – Space

+0

Попробуйте прочитать файл Режим NON BLOCK – sganesh

+0

Возможно, вы захотите закрыть файл в программе для записи, прежде чем открывать его в программе чтения. И как вы убеждаетесь, что чтение происходит только после записи? – AngryWhenHungry

ответ

-1

Вы на окнах или * nix? вы могли бы связать что-то вроде этого вместе на * nix, используя хвост, чтобы получить вывод, поскольку он записывается в файл. В Windows вы можете вызвать CreateFile() с FILE_SHARE_READ и/или FILE_SHARE_WRITE, чтобы другие могли получить доступ к файлу, пока вы его открыли для чтения/записи. вам может потребоваться периодически проверять, изменился ли размер файла, чтобы узнать, когда читать (я не уверен на 100% здесь).

другой вариант - это файл с отображением памяти.

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); 
} 
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, потому что у них нет другого способа синхронизации. По крайней мере один провалится, но нам все равно, пока труба существует.

Как вы можете видеть, все машины ожидания обслуживаются системой, поэтому вы делаете то, о чем заботитесь: чтение и письмо.

Смежные вопросы