Apre il file con nome ESPR, e gli associa FILEHANDLE.
(Quella che segue èegue una documentazione completa di open(): per un'introduzione più semplice prendete in considerazione la lettura perlopentut).
Se FILEHANDLE è una variabile scalare non definita (oppure un
elemento di un array o di un hash), le viene assegnato un riferimento
ad un filehandle anonimo, diversamente se FILEHANDLE è
un'espressione, il suo risultato è usato come nome del
filehandle voluto. (Questo potrebbe esser considerato
come un riferimento simbolico, in questo caso use strict 'refs'
potrebbe non essere efficace).
Se EXPR viene omesso, verrà usata la variabile come scalare
dello stesso nome di FILEHANDLE. (Si noti che le variabili lessicali,
quelle dichiarate con my, non funzioneranno per questo scopo;
in questo caso se usate my, specificate ESPR nella chiamata a open).
Se vengono specificati tre o più argomenti la modalità
di apertura e il nome del file sono separati. Se MODE è '<'
oppure nulla, il file è aperto in lettura. Se MODE è
''> il file viene troncato e aperto in scrittura, oppure creato
se necessario. Se MODE è '>'> il file viene aperto in
append mode oppure creato se necessario ["append mode" significa
scrittura dalla fine del file, NdT].
Potete mettere un '+' davanti a ''> oppure '<' per
indicare che intendete sia leggere che scrivere sul file; per questo
'+<' è quasi sempre preferito per aggiornamenti in
lettura/scrittura, la modalità '+'> prima
troncherà il file. Di norma non potete usare la modalità
di lettura/scrittura per aggiornare file di testo, dato che hanno una
lunghezza di record non fissa. Controllate l'opzione -i in perlrun
per un miglior approccio al problema. Il file viene creato con permessi
0666 modificati dalla umask impostata per il processo.
Questi vari prefissi corrispondono ai parametri mode di fopen(3) 'r',
'r+', 'w', 'w+', 'a' e 'a+'.
Nel caso d'uso a 2 argomenti (e 1 argomento) il MODE e il FILENAME devono
essere concatenati (nel modo citato), possibilmente separati da spazi.
Non è possibile omettere il MODE in questi casi se si intende
usare '<'.
Se il FILENAME inizia per '|' verrà interpretato come un comando
al quale gli verrà inviato dell'output come pipe, e se FILENAME
finisce per '|' verrà interpretato come un comando che invierà
il suo output a noi. Consultate perlipc/"Using open() for IPC" ["Usare open() per IPC", NdT]
per altri esempi su questo caso. (Non è ammesso l'uso di open per eseguire un
comando e accedervi in scrittura e in lettura, consultate IPC::Open2,
IPC::Open3 e perlipc/"Bidirectional Communication with Another Process"
["Comunicazioni bidirezionali con un altro processo", NdT] per delle alternative).
Per tre o più argomenti, se MODO è '|-', il nome del file viene
interpretato come un comando al quale gli verrà inviato dell'output come pipe e se
MODO è '-|', il nome del file verrà interpretato come un comando che
invierà il suo output a noi. Nel caso della versione a 2 argomenti (e 1 argomento), si
dovrebbe sostituire il trattino ('-') con il comando.
Consultate perlipc/"Using open() for IPC" ["Usare open() per IPC", NdT]
per altri esempi su questo caso. (Non è ammesso l'uso di open per eseguire un
comando e accedervi in scrittura e in lettura, consultate IPC::Open2,
IPC::Open3 e perlipc/"Bidirectional Communication"
["Comunicazioni bidirezionali", NdT] per delle alternative).
Nel caso della versione a tre o più argomenti della apertura delle pipe, se
LIST è specificato (ulteriore parametro dopo il nome comando) allora
LIST diventa la lista dei parametri da inviare al comando quando invocato, se la
piattaforma in uso lo permette. Il significato di open con più di tre
argomenti per chiamate diverse dalle pipe non è specificato.
Alcuni "layers" sperimentali potrebbero fornire parametri ulteriori per
dare significato a LIST.
Nel caso della versione a 2 argomenti (e 1 argomento), l'apertura di '-'
significa la lettura di STDIN mentre '-'> l'apertura di STDOUT.
Potete usare i tre parametri per aprire specifici "strati" di IO (altrimenti noti come "disciplines" [letteralmente "ordini, discipline", NdT]) che verranno applicati all'handle, i quali modificano il funzionamento di come input e output vengono processatti (consultate open e PerlIO per ulteriori dettagli). Per esempio
open(FH, "<:utf8", "file")
aprirà il file codificato UTF-8 contenente caratteri Unicode,
si veda perluniintro. Va notato che se lo strato è specificato
nel caso di tre parametri, gli strati impostati di default dalla direttiva
open vengono ignorati.
Open restituisce un valore diverso da zero in caso di successo, il valore
indefinito diversamente. Se la open presenta una pipe, il valore restituito
può essere il PID del processo figlio.
Se si esegue Perl su un sistema che distingue fra file di testo e file binari,
controllate binmode per alcuni consigli su come gestire questi casi. La
chiave di distinzione fra sistemi che richiedono binmode e quelli che non
lo richiedono è il loro formato di file di testo. Sistemi come Unix,
Mac OS e Plan 9, che delimitano le linee con un singolo carattere, codificato
in C come "\n", non richiedono binmode. Gli altri lo richiedono.
Quando si apre un file, non è buona norma continuare la normale
esecuzione se la chiamata fallisce, per questa ragione open viene
frequentemente usata con die. Anche se die non farà quanto
voluto (nel caso di script CGI, dove vorreste ottenere una pagina di
errore formattata (ma ci sono dei moduli che possono aiutare con questo
problema)) dovreste sempre controllare il valore restituito dalla apertura
di un file. Fa eccezione il raro caso quando si intende usare un filehandle
NON aperto.
Un caso speciale, la versione a 3 argomenti in modalità
lettura/scrittura dove il terzo parametro sia undef:
open(TMP, "+>", undef) or die ...
che apre un filehandle su un file temporaneo anonimo. Inoltre, l'utilizzo di "+<" funziona per simmetria ma dovreste realmente considerare di scrivere prima qualcosa sul file temporaneo. Avrete la necessitè di utilizzare seek() per effettuare la lettura.
A partire dalla version 5.8.0, il perl è stato compilato usando PerlIO di default. A meno che voi non abbiate cambiato questo aspetto (cioè Configure -Uuseperlio), potete aprire i filehandle in file "in memoria" mantenuti entro scalari Perl tramite:
open($fh, '>', \$variabile) || ..
Tuttavia, se volete riaprire STDOUT oppure STDERR come file
"in memoria", prima dovete chiuderli:
close STDOUT;
open STDOUT, '>', \$variabile or die "Impossibile aprire STDOUT: $!";
Esempio:
$ARTICOLO = 100;
open ARTICOLO or die "Impossibile trovare l'articolo $ARTICOLO: $!\n";
while (<ARTICOLO>) {...
open(LOG, '>>/usr/spool/news/twitlog'); # (log e` riservato)
# se la open fallisce, l'output viene perso
open(DBASE, '+<', 'dbase.mine') # aperto per aggiornare or die "Impossibile aprire 'dbase.mine' per aggiornare: $!";
open(DBASE, '+<dbase.mine') # piu` rapidamente or die "Impossibile aprire 'dbase.mine' per aggiornare: $!";
open(ARTICLE, '-|', "caesar <$article") # decodifica articolo or die "Impossibile avviare caesar: $!";
open(ARTICLE, "caesar <$article |") # piu` rapidamente or die "Impossibile avviare caesar: $!";
open(EXTRACT, "|sort >Tmp$$") # $$ e` il pid del nostro processo or die "Impossibile avviare sort: $!";
# in memory files
open(MEMORY,'>', \$var)
or die "Impossibile aprire il file in memoria: $!";
print MEMORY "pippo!\n"; # l'output andra` a finire in $var
# processa la lista degli argomenti dei file insieme con ogni include
foreach $file (@ARGV) {
process($file, 'fh00');
}
sub process {
my($nomefile, $input) = @_;
$input++; # questo e` un incremento di stringa
unless (open($input, $nomefile)) {
print STDERR "Impossibile aprire $nomefile: $!\n";
return;
}
local $_;
while (<$input>) { # si noti l'uso di indirezione
if (/^#include "(.*)"/) {
process($1, $input);
next;
}
#... # qualunque cosa
}
}
Consultate perliol per informazioni dettagliate su PerlIO.
Inoltre potete, nella tradizione della Bourne shell, specificare un EXPR
che inizia con '&'>, nel qual caso il resto della stringa viene
interpretato come un filehandle (o descrittore di file, se è numerico)
per essere duplicato (come dup(2)) e aperto. Potete usare & dopo >, >>,
<, +>, +>> e +<. La modalità che
specificate deve essere uguale alla modalità del filehandle originale.
(Duplicare un filehandle non entra nel merito dell'esistenza di precedenti buffer
di IO). Se usate la versione a 3 argomenti, potete passare un numero, il nome di
un filehandle oppure un normale "riferimento ad un glob".
Ecco uno script che salva, redirige e ripristina STDOUT e STDERR usando
diversi metodi:
#!/usr/bin/perl
open my $vecchioout, ">&STDOUT" or die "Impossibile duplicare STDOUT: $!";
open VECCHIOERR, ">&", \*STDERR or die "Impossibile duplicare STDERR: $!";
open STDOUT, '>', "pippo.out" or die "Impossibile redirezionare STDOUT: $!";
open STDERR, ">&STDOUT" or die "Impossibile duplicare STDOUT: $!";
select STDERR; $| = 1; # rendiamolo non bufferizzato
select STDOUT; $| = 1; # rendiamolo non bufferizzato
print STDOUT "stdout 1\n"; # questo funziona
print STDERR "stderr 1\n"; # anche per sottoprocessi
open STDOUT, ">&", $vecchioout or die "Impossibile duplicare \$vecchioout: $!";
open STDERR, ">&VECCHIOERR" or die "Impossibile duplicare VECCHIOERR: $!";
print STDOUT "stdout 2\n";
print STDERR "stderr 2\n";
Se specificate '<&=X', dove X è un numero descrittore di file,
oppure un filehandle, allora Perl eseguirà l'equivalente della funzione C
fdopen su quel descrittore di file (e non chiamerà dup(2)); questo
è un modo d'uso più parsimonioso dei descrittori di file.
Per esempio:
# apertura in input, riutilizzando il fileno di $fd
open(FILEHANDLE, "<&=$df")
oppure
open(FILEHANDLE, "<&=", $df)
oppure
# apertura in aggiornamento, utilizzando il fileno di VECCHIOFH
open(FH, ">>&=", VECCHIOFH)
oppure
open(FH, ">>&=VECCHIOFH")
Essere parsimoniosi sui filehandle è utile anche (al di
là dell'essere parsimoniosi) per esempio quando qualcosa
è dipendente dai descrittori dei file, come per esempio
l'uso di lock tramite flock(). Se utilizzate semplicemente
open(A, '>&B')>, il filehandle A non avrà lo stesso
descrittore di file che ha B e quindi flock(A) non farà
un flock(B) e viceversa. Ma con open(A, '>&=B')> il
filehandle condividerà lo stesso descrittore di file.
Va notato che se state usando un Perl più vecchio della 5.8.0., Perl userà la fdopen() della libreria C standard per implementare la funzionalità "=". Su molti sistemi Unix, fdopen() fallisce quando dei descrittori di file eccedono un certo valore, tipicamente 255. Per le versioni di Perl 5.8.0 e precedenti, PerlIO è molto spesso la norma.
Potete vedere se il Perl è stato compilato con PerlIO eseguendo
perl -V e cercando la linea userperlio=. Se useperlio è
define, avete PerlIO, altrimenti no.
Se aprite una pipe col comando '-', cioè sia con '|-' o
'-|' con la versione a 2 argomenti (o 1) di open(), allora viene eseguita
una fork implicita e restituito il pid del processo figlio per il processo
padre, 0 al processo figlio. (Usate defined($pid) per determinare
se la open ha avuto successo). Il filehandle si riconduce di norma al
padre, ma l'input/output su quel filehandle viene passato attraverso
pipe da/per lo STDOUT/STDIN del processo figlio. Nel processo figlio il
filehandle non è aperto, l'input/output avviene dal/al nuovo STDIN
o STDOUT. Solitamente questo viene usato come il normale open con pipe quando
volete esercitare maggior controllo proprio su come viene eseguito il comando
pipe, come quando state eseguendo setuid e non si vuole controllare il comando
shell per i metacaratteri. Le seguenti triple sono più o meno
equivalenti:
open(PIPPO, "|tr '[a-z]' '[A-Z]'");
open(PIPPO, '|-', "tr '[a-z]' '[A-Z]'");
open(PIPPO, '|-') || exec 'tr', '[a-z]', '[A-Z]';
open(PIPPO, '|-', "tr", '[a-z]', '[A-Z]');
open(PIPPO, "cat -n '$file'|");
open(PIPPO, '-|', "cat -n '$file'");
open(PIPPO, '-|') || exec 'cat', '-n', $file;
open(PIPPO, '-|', "cat", '-n', $file);
Nell'ultimo esempio, in ogni blocco di codice viene mostrata la pipe come
"list form" [un elenco di parametri, NdT], non supportato da alcuna
piattaforma. Una buona regola è: se il vostro sistema operativo
ha una vera fork() (in altre parole, se è UNIX) putete usare la
list form.
Consultate perlipc/"Safe Pipe Opens" ["Apertura sicura di pipe", NdT] per ulteriori esempi.
A partire dalla versione 5.6.0, Perl tenta di svuotare i buffer, tutti i file
aperti in output prima di qualsiasi operazione che potrebbe effettuare il fork,
ma questo potrebbe non essere supportato su qualche piattaforma (si veda
perlport). Per essere sicuri, dovreste impostare $| ($AUTOFLUSH nel modulo
English) oppure chiamare il metodo autoflush() di IO::Handle su ogni handle
aperto.
Su sistemi che supportano i flag close-on-exec ["chiuso-su-esecuzione", NdT], il flag sarà impostato per ogni nuovo descrittore di file aperto, come determinato dal valore di $^F. Si veda perlvar/$^F.
Chiudere uno qualsiasi dei filehandle di pipe provoca l'attesa del processo
padre che il processo figlio finisca, restituendo lo stato in $?.
Il nome del file passato nella chiamata alla open() nella versione con 2 argomenti (o 1) avrà gli spazi in testa e coda eliminati, e i normali caratteri di redirezione verranno onorati. Questa proprietà, nota come "magic open" ["apertura magica", NdT], può spesso essere usata con buoni esiti. Un utente potrebbe specificare un nomefile tipo "rsh cat file |", oppure voi potreste cambiare alcuni particolari nomifle in base alle necessità:
$nomefile =~ s/(.*\.gz)\s*$/gzip -dc < $1|/;
open(FH, $nomefile) or die "Impossibile aprire $nomefile: $!";
Usate la versione della open a 3 argomenti per aprire un file che contiene strani caratteri arbitrari,
open(PIPPO, '<', $file);
oppure potrebbe essere necessario proteggere un qualsiasi spazio a inizio o fine nome:
$file =~ s#^(\s)#./$1#;
open(PIPPO, "< $file\0");
(questo potrebbe non funzionare su qualche bizzarro filesystem). Uno potrebbe scegliere, in coscienza, fra la versione magica e la versione a tre argomenti di open():
open IN, $ARGV[0];
permette all'utente di specificare un parametro della forma "rsh cat file |",
ma non funziona su un nome file con uno spazio, mentre
open IN, '<', $ARGV[0];
ha esattamente le restrizioni opposte.
Se volete una "vera" open in stile C (consultate open(2) sul vostro sistema),
dovrete usare la funzione sysopen, la quale non implica questo genere di "magia"
(ma potrebbe usare alcuni differenti filemode rispetto alla open() del Perl, i
quali sono mappati alla fopen() del C). Questa è un'altra possibilita per
proteggere meglio il vostro nome file dalle interpretazioni.
Per esempio:
use IO::Handle;
sysopen(HANDLE, $path, O_RDWR|O_CREAT|O_EXCL)
or die "sysopen $path: $!";
$vecchiofh = select(HANDLE); $| = 1; select($vecchiofh);
print HANDLE "Delle cose $$\n";
seek(HANDLE, 0, 0);
print "Il file contiene: ", <HANDLE>;
Usando il costruttore dal package IO::Handle (oppure una delle delle sue
sottoclassi, tipo IO::File oppure IO::Socket), potete generare filehandle
anonimi che hanno come scope lo stesso di una qualsiasi variabile che possa
contenere riferimenti, e automaticamente chiusi comunque, ogniqualvolta uscite
da tale scope:
use IO::File;
#...
sub leggo_miofile_munged {
my $TUTTO = shift;
my $handle = new IO::File;
open($handle, "miofile") or die "miofile: $!";
$primo = <$handle>
or return (); # Qui viene chiuso autimaticamente.
mung $primo or die "mung fallito"; # Oppure qui.
return $primo, <$handle> if $TUTTO; # Oppure qui.
$primo; # Oppure qui.
}
Consultate seek per qualche dettaglio riguardo la possibilità di mescolare letture e scritture.