我如何确定Perl文件句柄是读取还是写入句柄?

14
您有一个 IO::File 对象或类型 glob(\*STDOUTSymbol::symbol_to_ref("main::FH"));您该如何确定它是读取还是写入句柄?接口不能扩展以传递此信息(我正在重写 close 添加调用 flushsync 在实际关闭之前)。
目前,我正在尝试 flushsync 文件句柄,并忽略错误 "Invalid argument"(当我尝试在读取文件句柄上执行 flushsync 时会出现此错误)。
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: $!";
        }
};

+1 太棒了!我不知道我什么时候会用到这个,但我很想知道有人需要它。 - Shalom Craimer
Ext4 带来了 Ext3 隐瞒了一段时间的问题。请参见 http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ 和正在进行的 p5p 线程 (http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2009-03/msg00322.html) 了解背景。 - Chas. Owens
1个回答

8

看一下fcntl选项。也许是使用F_GETFLO_ACCMODE

编辑:我在午餐时间做了一些谷歌搜索和尝试,这里有一些可能不可移植的代码,但它适用于我的Linux系统,也可能适用于任何Posix系统(也许甚至包括Cygwin,谁知道呢?)。

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

示例输出:

$ perl test.pl 
out
File is: Write only

in
File is: Read only

both
File is: Read / Write

看起来fcntl是特定于操作系统的,但如果它适用于给定的操作系统,我可能会基于该操作系统构建一个调度哈希,并在当前操作系统不在调度哈希中时回退到我的当前代码。 - Chas. Owens
1
不要硬编码“3”,你可以使用 O_RDONLY | O_RDWR | O_WRONLY,但是这些常量很可能不会改变,因为它们已经保持了20年。尽管如此,这样做可以使代码更易读。 - JasonSmith
我可以访问OS X、Linux、FreeBSD和WinXP;如果它在所有这些系统上都能运行,那么这可能就是答案。 - Chas. Owens
它似乎适用于 IO::File 对象,但不适用于类型符号,现在是时候看看如何将类型符号升级为 IO::File 了。 - Chas. Owens
1
看起来我像是吸食了可卡因,但实际上它对类型环境、标准输入输出流都可以正常工作。当我使用一个文件时,我只需要打开它就好了。 - Chas. Owens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接