2009-02-06 23 views

risposta

36

Vedere answer regarding openhandle() from Scalar::Util. La risposta che ho originariamente scritto qui era una volta il meglio che potevamo fare, ma ora è mal datato.

+0

Funziona, Thanks :) –

+10

causa l'errore: ... dire() sul filehandle aperto ... – ekerner

+1

@ ekerner tecnicamente non è un errore ma un avvertimento. – vladr

12

Perché vuoi farlo? L'unica ragione per cui riesco a pensare è quando si utilizzano i filehandle del pacchetto vecchio stile (che si sembra stiano facendo) e si vuole evitare di salvare accidentalmente un handle rispetto a un altro.

Questo problema può essere risolto utilizzando i nuovi filehandle indiretti di stile.

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

Oh bene, buono a sapersi. Grazie. –

+0

matt: prova Perl :: Critico per uno stile migliore –

+0

Motivo di esempio perché: diciamo che hai aperto un filehandle con 'open (FH," - | ")'. Volete assicurarvi che il processo forked abbia successo, il che richiede esplicitamente 'close FH' per impostare' $! 'O' $? 'Appropriatamente. Se non ha avuto successo, vuoi generare un errore; tuttavia, non si vuole generare un errore se qualcos'altro ha già chiuso 'FH'. – jon

8

Perl fornisce la funzione fileno proprio per questo scopo.

EDIT Sono stato corretto per lo scopo di fileno(). Io preferisco il test più breve

fileno FILEHANDLE

oltre

tell FH != -1

+1

Beh ... non proprio.Fornisce fileno allo scopo di ottenere il numero del descrittore del file di sistema. Determinare se il filehandle è aperto è un effetto collaterale (proprio come è un effetto collaterale di tell). – chaos

+1

E nemmeno un effetto collaterale completamente affidabile. È possibile avere un filehandle che è aperto a qualcosa di diverso da un filedescriptor, nel qual caso 'fileno' restituisce sensibilmente undef. Esempi sono maniglie e maniglie legate aperte agli scalari. – hobbs

+1

tell (FH) genera un avviso con un filehandle chiuso. Usare fileno() no. –

0

Perché ti interessa se è già aperta? Stai cercando di catturare letture simultanee?

Non è necessario preoccuparsi di chiudere il file. O non è aperto e la chiusura fallisce perché non ha nulla da chiudere, o il file è aperto e la chiusura lo rilascia. In entrambi i casi, il file non è aperto su quel filehandle. Chiudi il filehandle senza preoccuparti se non è aperto. Stai vedendo qualcosa di strano lì?

+0

Esempio di motivo per cui: Supponiamo che tu abbia aperto un filehandle con open (FH, "- |"). Volete assicurarvi che il processo biforcato abbia successo, il che richiede un FH esplicitamente chiuso per impostare $! o $? appropriatamente. Se non ha avuto successo, vuoi generare un errore; tuttavia, non si vuole generare un errore se qualcos'altro ha già chiuso FH. – jon

+0

-1 per la risposta inutile. Se vuoi discutere se l'obiettivo della domanda è effettivamente desiderabile, ritengo che sia meglio fare come commento. – jon

+0

Ti manca il punto. Ci sono alcune cose in cui non ci interessa se falliscono perché finiamo con il risultato che volevamo in entrambi i casi. Non dobbiamo fare molto lavoro per causare il risultato o controllarlo perché otteniamo la stessa cosa in entrambi i casi. –

1

di Tell produce un avvertimento (così fa stat, -s, -e, ecc ..) con 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 

Le alternative fileno($fh) e eof($fh) non producono gli avvertimenti. Ho trovato che l'alternativa migliore era salvare l'output da open.

+0

'eof' ha effetti collaterali. Vedi i suoi documenti. – jon

21

Il modulo Scalar::Util fornisce la funzione openhandle() per questo. A differenza di fileno(), gestisce i filehand perl che non sono associati ai filehandle del sistema operativo. A differenza tell(), non produce avvisi quando utilizzato su un filehandle non aperto Dal modulo 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

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

+2

Questo è l'unico vero soluzione, grazie. – ekerner

+1

La risposta di tchrist alla domanda @ link di daxim è piuttosto spettacolare, ma sembra essere solo diversa da openhandle in quanto ti dirà che la stringa "STDIN" è aperta (che tecnicamente è, a quanto pare, come puoi usarla per stampa ecc.) Ora se mai vorrai incoraggiare questo genere di cose è un'altra domanda; Tenderei a vedere il rifiuto di openhandle di "STDIN" come più di una caratteristica di un bug. –

Problemi correlati