2009-02-06 11 views

Antwort

36

Bitte siehe answer regarding openhandle() from Scalar::Util. Die Antwort, die ich ursprünglich hier geschrieben habe, war einst die beste, die wir machen konnten, aber sie ist jetzt sehr veraltet.

+0

Es funktioniert, Thanks :) –

+10

Fehler verursacht: ... sagen() auf ungeöffnete Dateihandle ... – ekerner

+1

@ Ekerner technisch kein Fehler, sondern eine Warnung. – vladr

12

Warum möchten Sie das tun? Der einzige Grund, an den ich denken kann, ist, wenn Sie Pakethandles im alten Stil verwenden (was Sie anscheinend tun) und verhindern wollen, dass versehentlich ein Griff vor einem anderen gehalten wird.

Dieses Problem kann durch Verwenden von neuen indirekten Dateihandles gelöst werden.

open my $fh, '<', $filename or die "Couldn't open $filename: $!"; 
+0

Oh großartig, gut zu wissen. Vielen Dank. –

+0

matt: versuche Perl :: Critic für besseren Stil –

+0

Beispiel Grund warum: Angenommen, Sie haben ein Dateihandle mit 'open (FH," - | ")' geöffnet. Sie möchten sicherstellen, dass der Fork-Prozess erfolgreich ist, was explizit 'close FH' erfordert, um' $! 'Oder' $? 'Entsprechend zu setzen. Wenn dies nicht erfolgreich war, möchten Sie einen Fehler melden. Sie möchten jedoch keinen Fehler melden, wenn etwas anderes 'FH' bereits geschlossen hat. – jon

8

Perl bietet die fileno Funktion genau für diesen Zweck.

EDIT Ich stehe auf den Zweck von fileno() korrigiert. Ich ziehe den kürzeren Test

fileno FILEHANDLE

über

tell FH != -1

+1

Nun ... nicht wirklich.Es stellt fileno für den Zweck zur Verfügung, die Systemdateideskriptornummer zu erhalten. Das Bestimmen, ob das Dateihandle geöffnet ist, ist ein Nebeneffekt (genauso wie es ein Nebeneffekt von tell ist). – chaos

+1

Und auch keine absolut zuverlässige Nebenwirkung. Es ist möglich, ein Dateihandle zu haben, das zu etwas anderem als einem Dateideskriptor offen ist, in welchem ​​Fall 'fileno' sinnvollerweise undef zurückgibt. Beispiele sind gebundene Griffe und Griffe, die für Skalare geöffnet sind. – hobbs

+1

Tell (FH) erzeugt eine Warnung mit einem geschlossenen Dateihandle. Mit fileno() funktioniert das nicht. –

0

Warum interessieren Sie sich, wenn es bereits geöffnet ist? Versuchen Sie, simultane Lesevorgänge zu erfassen?

Sie müssen sich nicht wirklich um das Schließen der Datei kümmern. Entweder ist es nicht geöffnet und das Schließen schlägt fehl, weil es nichts zu schließen hat oder die Datei geöffnet ist und das Schließen es freigibt. In beiden Fällen ist die Datei auf diesem Dateihandle nicht geöffnet. Schließen Sie einfach den Dateigriff, ohne ihn zu beachten, wenn er nicht geöffnet ist. Siehst du dort etwas Seltsames?

+0

Beispiel Grund warum: Nehmen wir an, Sie haben ein Dateihandle mit open geöffnet (FH, "- |"). Sie möchten sicherstellen, dass der Fork-Prozess erfolgreich ist, was explizit das Schließen von FH erfordert, um $! oder $? passend. Wenn dies nicht erfolgreich war, möchten Sie einen Fehler melden. Sie möchten jedoch keinen Fehler melden, wenn FH bereits geschlossen wurde. – jon

+0

-1 für die nicht hilfreiche Antwort. Wenn Sie darüber diskutieren wollen, ob das Ziel der Frage tatsächlich wünschenswert ist, ist das meiner Ansicht nach besser als Kommentar zu verstehen. – jon

+0

Sie vermissen den Punkt. Es gibt einige Dinge, bei denen es uns egal ist, ob sie scheitern, weil wir mit dem Ergebnis enden, das wir auf jede Art wollten. Wir müssen nicht viel arbeiten, um das Ergebnis zu verursachen oder es zu überprüfen, weil wir das gleiche in beiden Richtungen bekommen. –

1

Tells eine Warnung erzeugt (so auch stat, -s, -e, etc ..) mit use warnings (-W)

perl -wle ' 
    open my $fh, "<", "notexists.txt"; 
    print "can stat fh" if tell $fh 
' 
tell() on closed filehandle $fh at -e line 1. 
-1 

Die Alternativen fileno($fh) und eof($fh) keine Warnungen erzeugen. Ich fand die beste Alternative, um die Ausgabe von open zu speichern.

+0

'eof' hat Nebenwirkungen. Siehe seine Dokumentation. – jon

21

Das Modul Scalar::Util bietet hierfür die Funktion openhandle(). Im Gegensatz zu fileno() behandelt es Perl-Dateihandles, die nicht mit OS-Dateihandles verknüpft sind. Im Gegensatz zu tell(), spielt es keine Warnungen erzeugen, wenn sie auf einer ungeöffnete Dateikennung Aus dem Modul der verwendeten documentation:

openhandle FH

Returns FH if FH may be used as a filehandle and is open, or FH is a tied handle. Otherwise "undef" is returned. 

    $fh = openhandle(*STDIN);   # \*STDIN 
    $fh = openhandle(\*STDIN);   # \*STDIN 
    $fh = openhandle(*NOTOPEN);   # undef 
    $fh = openhandle("scalar");   # undef 
+2

[openhandle Einschränkungen] (http://stackoverflow.com/questions/3807231/how-can-i-test-if-i-can-write-to-a-filehandle/4200474#4200474) – daxim

+2

Dies ist das einzige wirklich Lösung, danke. – ekerner

+1

tchrists Antwort auf die Frage @daxim links ist ziemlich spektakulär, aber scheint sich nur von openhandle zu unterscheiden, da es Ihnen sagen wird, dass die Zeichenkette "STDIN" offen ist (was es technisch ist, so scheint es, wie Sie es benutzen können) drucken usw.) Nun, ob Sie diese Art von Ding wirklich jemals ermutigen möchten, ist eine andere Frage; Ich würde eher die offene Ablehnung von "STDIN" als eher ein Feature als einen Bug sehen. –

Verwandte Themen