Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine whether a Perl file handle is a read or write handle?

You are given either an IO::File object or a typeglob (\*STDOUT or Symbol::symbol_to_ref("main::FH")); how would you go about determining if it is a read or write handle? The interface cannot be extended to pass this information (I am overriding close to add calls to flush and sync before the actual close).

Currently I am attempting to flush and sync the filehandle and ignoring the error "Invalid argument" (which is what I get when I attempt to flush or sync a read filehandle):

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: $!";
        }
};
like image 409
Chas. Owens Avatar asked Mar 23 '09 04:03

Chas. Owens


People also ask

How read and write in Perl?

If you want to open a file for reading and writing, you can put a plus sign before the > or < characters. open DATA, "+>file. txt" or die "Couldn't open file file.

What is a Perl file handle?

In Perl, a FileHandle associates a name to an external file, that can be used until the end of the program or until the FileHandle is closed.

How do I read the contents of a file in Perl?

use File::Slurp; my $file_content = read_file('text_document. txt'); File::Slurp's read_file function to reads the entire contents of a file with the file name and returns it as a string. It's simple and usually does what it's expected to do.


1 Answers

Have a look at the fcntl options. Maybe F_GETFL with O_ACCMODE.

Edit: I did a little googling and playing over lunch and here is some probably non-portable code but it works for my Linux box, and probably any Posix system (perhaps even Cygwin, who knows?).

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);

Example output:

$ perl test.pl 
out
File is: Write only

in
File is: Read only

both
File is: Read / Write
like image 198
JasonSmith Avatar answered Oct 28 '22 06:10

JasonSmith