2009-03-23 18 views
12

Viene fornito un oggetto IO::File o un typeglob (\*STDOUT o Symbol::symbol_to_ref("main::FH")); come andresti a determinare se si tratta di un handle di lettura o scrittura? L'interfaccia non può essere estesa per passare queste informazioni (sto ignorando close per aggiungere chiamate a flush e sync prima della chiusura effettiva).Come determinare se un handle di file Perl è un handle di lettura o scrittura?

Attualmente sto cercando di flush e sync il filehandle e ignorando l'errore "Invalid argument" (che è quello che ottengo quando tentare di flush o sync un filehandle lettura):

eval { $fh->flush; 1 } or do { 
     #this seems to exclude flushes on read handles 
     unless ($! =~ /Invalid argument/) { 
       croak "could not flush $fh: $!"; 
     } 
}; 

eval { $fh->sync; 1 } or do { 
     #this seems to exclude syncs on read handles 
     unless ($! =~ /Invalid argument/) { 
       croak "could not sync $fh: $!"; 
     } 
}; 
+0

+1 Eccellente domanda! Non ho idea di quando lo userei mai, ma sono affascinato dal sapere che qualcuno ha bisogno di questo. – scraimer

+0

Ext4 ha sollevato problemi che Ext3 aveva tenuto nascosto per un po '. Vedi http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ e il thread p5p in corso (http://www.xray.mpe.mpg.de/mailing-lists /perl5-porters/2009-03/msg00322.html) per lo sfondo. –

risposta

7

Dai un'occhiata alla fcntl opzioni. Forse F_GETFL con O_ACCMODE.

Edit: ho fatto un po 'googling e giocando durante il pranzo ed ecco alcune probabilmente il codice non portabile ma funziona per la mia macchina Linux, e probabilmente qualsiasi sistema Posix (forse anche Cygwin, chi lo sa?) . uscita

use strict; 
use Fcntl; 
use IO::File; 

my $file; 
my %modes = (0 => 'Read only', 1 => 'Write only', 2 => 'Read/Write'); 

sub open_type { 
    my $fh = shift; 
    my $mode = fcntl($fh, F_GETFL, 0); 
    print "File is: " . $modes{$mode & 3} . "\n"; 
} 

print "out\n"; 
$file = new IO::File(); 
$file->open('> /tmp/out'); 
open_type($file); 

print "\n"; 

print "in\n"; 
$file = new IO::File(); 
$file->open('< /etc/passwd'); 
open_type($file); 

print "\n"; 

print "both\n"; 
$file = new IO::File(); 
$file->open('+< /tmp/out'); 
open_type($file); 

Esempio:

$ perl test.pl 
out 
File is: Write only 

in 
File is: Read only 

both 
File is: Read/Write 
+0

Sembra che fcntl sia specifico del sistema operativo, ma se funziona per un determinato sistema operativo, potrei semplicemente creare un hash di spedizione basato sul sistema operativo e tornare al mio codice corrente se il sistema operativo attuale non è nell'hash di invio. –

+0

Felice che ti piaccia. Ho messo un po 'di codice di test. – JasonSmith

+0

Invece di hard coding '3' si potrebbe fare 'O_RDONLY | O_RDWR | O_WRONLY' ma è improbabile che queste costanti cambino poiché non sono cambiate da 20 anni. Tuttavia, rende il codice più leggibile. – JasonSmith

Problemi correlati