2009-03-23 29 views
12

Bạn được cung cấp một đối tượng IO::File hoặc typeglob (\*STDOUT hoặc Symbol::symbol_to_ref("main::FH")); làm thế nào bạn sẽ đi về xác định nếu nó là một xử lý đọc hoặc viết? Giao diện không thể mở rộng để chuyển thông tin này (tôi ghi đè close để thêm các cuộc gọi đến flushsync trước khi đóng thực tế).Làm thế nào để xác định liệu một xử lý tập tin Perl là một xử lý đọc hoặc viết?

Hiện nay tôi đang cố gắng để flushsync filehandle và bỏ qua những lỗi "Invalid argument" (đó là những gì tôi nhận được khi tôi cố gắng để flush hoặc sync một filehandle đọc):

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 Fantastic câu hỏi! Tôi không biết khi nào tôi sẽ sử dụng nó, nhưng tôi thích thú khi biết ai đó cần điều này. – scraimer

+0

Ext4 đã đưa ra các vấn đề mà Ext3 đã giữ ẩn trong một thời gian. Xem http://thunk.org/tytso/blog/2009/03/15/dont-fear-the-fsync/ và chuỗi p5p đang diễn ra (http://www.xray.mpe.mpg.de/mailing-lists /perl5-porters/2009-03/msg00322.html) cho nền. –

Trả lời

7

Có một cái nhìn tại fcntl tùy chọn. Có thể F_GETFL với O_ACCMODE.

Edit: Tôi đã làm một chút googling và chơi trong bữa ăn trưa và đây là một số lẽ không cầm tay mã nhưng nó hoạt động cho hộp Linux của tôi, và có lẽ bất kỳ hệ thống Posix (thậm chí Cygwin, ai mà biết được?) . sản lượng

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

Ví dụ:

$ perl test.pl 
out 
File is: Write only 

in 
File is: Read only 

both 
File is: Read/Write 
+0

Dường như fcntl là hệ điều hành cụ thể, nhưng nếu nó hoạt động cho một hệ điều hành cụ thể, tôi có thể xây dựng một băm công văn dựa trên hệ điều hành và quay trở lại mã hiện tại của tôi nếu hệ điều hành hiện tại không có trong công cụ băm. –

+0

Vui vì bạn thích nó. Tôi đưa ra một số mã thử nghiệm. – JasonSmith

+0

Thay vì mã hóa cứng '3' bạn có thể thực hiện 'O_RDONLY | O_RDWR | O_WRONLY' nhưng những hằng số này rất khó thay đổi vì chúng không thay đổi trong 20 năm. Tuy nhiên, nó làm cho mã dễ đọc hơn. – JasonSmith

Các vấn đề liên quan