index | project | pods | responsabili |
NOMEperlopentut - tutorial sull'aprir cose in Perl
DESCRIZIONEPerl ha, integrati, due modi semplici per aprire il file: il sistema shell per la comodità, ed il sistema C per la precisione. Il sistema shell ha anche la forma a due e quella a tre argomenti, che hanno modalità differenti per quanto riguarda l'interpretazione del nome del file. A voi la scelta.
Apertura à la shellLa funzione $ mio_programma file1 file2 file3 $ mio_programma < inputfile $ mio_programma > outputfile $ mio_programma >> outputfile $ mio_programma | altro_programma $ altro_programma | mio_programma Ed ecco alcuni esempi un po' più avanzati: $ altro_programma | mio_programma f1 - f2 $ altro_programma 2>&1 | mio_programma - $ mio_programma <&3 $ mio_programma >&4 I programmatori abituati a costrutti del genere saranno lieti di sapere che Perl supporta direttamente queste modalità familiari utilizzando praticamente la stessa sintassi della shell.
Aperture SempliciLa funzione Ad esempio: open(INFO, "datafile") || die("impossibile aprire datafile: $!"); open(INFO, "< datafile") || die("impossibile aprire datafile: $!"); open(RISULT ,"> runstats") || die("impossibile aprire runstats: $!"); open(LOG, ">> logfile ") || die("impossibile aprire logfile: $!"); Se preferite la versione con meno punteggiatura, potete anche scrivere tutto ciò come segue: open INFO, "< datafile" or die "impossibile aprire datafile: $!"; open RISULT ,"> runstats" or die "impossibile aprire runstats: $!"; open LOG, ">> logfile " or die "impossibile aprire logfile: $!"; Vanno notate alcune cose. Prima di tutto, il segno di minore all'inizio è opzionale. Se omesso, Perl assume che volete aprire il file in lettura. Osservate anche che nel primo esempio si utilizza l'operatore logico
open INFO, ( "< datafile" || die "impossibile aprire datafile: $!" ); che non è sicuramente quel che volete. L'altra cosa importante da notare è che, proprio come nella shell, qualsiasi spazio prima o dopo il nome del file viene ignorato. Questo è corretto, perché non vorreste comportamenti differenti dalle istruzioni che seguono: open INFO, "<datafile" open INFO, "< datafile" open INFO, "< datafile" Ignorare gli spazi di contorno aiuta anche quando leggete il nome di un file da un altro file, e vi dimenticate di eliminare gli spazi prima di aprire: $nomefile = <INFO>; # oops, \n e` rimasto open(EXTRA, "< $nomefile") || die "impossibile aprire $nomefile: $!"; Non si tratta di un bug, ma di una caratteristica inserita
appositamente. Visto che Esiste anche una versione a tre parametri di open( INFO, ">", $datafile ) || die "Impossibile creare $datafile: $!"; In questo caso, il nome del file da aprire è la stringa vera e propria
nella variabile
Filehandle IndirettiIl primo argomento di open( my $in, $infile ) or die "Impossibile leggere $infile: $!"; while ( <$in> ) { # fai qualcosa con $_ } close $in; I filehandle indiretti semplificano la gestione degli spazi dei
nomi. Poiché i filehandle sono globali all'interno del pacchetto
corrente, due subroutine che provino ad aprire Un altro comportamento conveniente è dato dal fatto che un filehandle indiretto viene chiuso automaticamente quando va fuori visibilità o quando lo forzate su undef: sub prima_riga { open( my $in, shift ) && return scalar <$in>; # non e` richiesta alcuna close() }
Apertura di PipeNel linguaggio C, quando volete aprire un file utilizzando la libreria
di I/O standard, utilizzate la funzione Se il carattere iniziale è un simbolo pipe [il carattere ``|'', N.d.T.]
open(STAMPANTE, "| lpr -Plp1") || die "impossibile lanciare lpr: $!"; print STAMPANTE "bla bla bla\n"; close(STAMPANTE) || die "impossibile chiudere lpr: $!"; Se il carattere finale è un simbolo pipe, viene lanciato un nuovo comando ed aperto un filehandle in sola lettura che legge dall'uscita di tale comando. Questo vi consente di accedere in lettura, attraverso questo handle, a tutto ciò che il comando scrive sul proprio standard output. Ad esempio: open(RETE, "netstat -i -n |") || die "impossibile lanciare netstat: $!"; while (<RETE>) { } # fai qualcosa con l'input close(RETE) || die "impossibile chiudere netstat: $!"; Cosa succede se provate ad aprire una pipe da o verso un comando che
non esiste? Se possibile, Perl intercetterà il fallimneto ed imposterà
Se volete aprire una pipe bidirezionale, la libreria IPC::Open2 vi sarà di aiuto. Consultate perlipc/``Comunicazione Bidirezionale con un Altro Processo''.
Il File ``Meno''Nuovamente, seguendo il corso delle utilità standard disponibili
nella shell, la funzione Se ``meno'' può essere usato come l'input o l'output di default, cosa
succede se aprite una pipe verso o da ``meno''? Qual è il comando di
default che verrà lanciato? Beh, è lo stesso script che state eseguendo!
In realtà c'è una chiamata a
Mischiare Letture e ScrittureÈ possibile specificare l'accesso sia in lettura che in scrittura. Tutto ciò che dovete fare è mettere un simbolo ``+'' immediatamente prima del carattere di redirezione. Ma, come nella shell, utilizzare un ``minore'' su un file non ne crea mai uno nuovo: ne apre solo uno che già esiste. D'altro canto, utilizzare un ``maggiore di'' vi sporcherà sempre qualsiasi file esistente (poiché lo tronca a lunghezza zero), o ne crea uno nuovo di zecca se non ne esiste già uno. Aggiungendo un ``+'' per rendere la redirezione sia di lettura che di scrittura, non altera tali proprietà: funzionerà solo su file esistenti oppure vi sporcherà sempre il file esistente. open(WTMP, "+< /usr/adm/wtmp") || die "impossibile aprire /usr/adm/wtmp: $!"; open(SCREEN, "+> lkscreen") || die "impossibile aprire lkscreen: $!"; open(LOGFILE, "+>> /var/log/applog" || die "impossibile aprire /var/log/applog: $!"; Il primo esempio non creerà un nuovo file, mentre il secondo esempio
vi sporcherà sempre il file esistente. Il terzo esempio creerà un nuovo
file se necessario, e non sporcherà un eventuale file preesistente,
dandovi la possibilità di leggere da qualsiasi punto nel file,
laddove però potrete solo scrivere aggiungendo dati alla fine del file.
In breve, il primo caso è sostanzialmente più comune degli altri due,
che si rivelano sbagliati nella maggior parte dei casi. (Se conoscete il
linguaggio C, il ``più'' nella Di fatto, quando occorre aggiornare un file, a meno che non stiate lavorando su un file binario come nel caso di WTMP esposto in precedenza, probabilmente non vorrete utilizzare questo approccio per effettuare gli aggiornamenti. Piuttosto, il parametro Perl a linea di comando -i viene a darvi una mano. Il comando che segue prende tutti i file sorgente o di intestazione C, C++ o yacc, e cambia tutti i ``pippo'' in ``pluto'', lasciando la vecchia versione non modificata con il nome originale ed un'estensione ``.orig'' agganciata alla fine: $ perl -i.orig -pe 's/\bpippo\b/pluto/g' *.[Cchy] Questa rappresenta una scorciatoia per effettuare alcuni giochetti di ridenominazione, che sono in realtà il modo migliore per aggiornare i file di testo. Consultate anche la seconda domanda in perlfaq5 per maggiori dettagli.
FiltriUno degli usi più comuni per $ mioprogramma file1 file2 file3 può ottenere tutti i file elencati aperti ed elaborati, uno alla volta, utilizzando un costrutto semplice come: while (<>) { # fai qualcosa con $_ } Se Potete tranquillamente pre-elaborare l'array use Getopt::Std; # -v, -D, -o ARG, imposta $opt_v, $opt_D, $opt_o getopts("vDo:"); # -v, -D, -o ARG, imposta $args{v}, $args{D}, $args{o} getopts("vDo:", \%args); Oppure il modulo standard Getopt::Long per consentirvi di utilizzare argomenti con nome: use Getopt::Long; GetOptions( "verboso" => \$verboso, # --verboso "Debug" => \$debug, # --Debug "output=s" => \$output ); # --output=qualcosa oppure --output qualcosa Un'altra ragione per effettuare la pre-elaborazione degli argomenti può essere quello di impostare per default la lista di tutti i file, nel caso la lista degli argomenti sia vuota: @ARGV = glob("*") unless @ARGV; Potete persino filtrare via tutti quei file che non sono semplici file di testo. Il tutto è piuttosto silenzioso, ovviamente, e potreste preferire di menzionare esplicitamente all'utilizzatore quando effettuate operazioni di esclusione come questa: @ARGV = grep { -f && -T } @ARGV; Se state utilizzando le opzioni a riga di comando -n o -p, dovreste
confinare i cambiamenti a Ricordate che una $pwdinfo = `domainname` =~ /^(\(none\))?$/ ? '< /etc/passwd' : 'ypcat passwd |'; open(PWD, $pwdinfo) or die "impossibile aprire $pwdinfo: $!"; Questo genere di cose entra in gioco nell'elaborazione di filtraggio.
Poiché l'elaborazione di $ mioprogramma f1 "cmd1|" - f2 "cmd2|" f3 < tmpfile Questo programma leggerà dal file f1, dal processo cmd1, da standard input (ossia, tmpfile in questo caso), dal file f2, dal comando cmd2 ed infine dal file f3. Sì, tutto ciò significa anche che se nella vostra
directory avete file chiamati ``-'' (e
così via), questi non saranno elaborati da Una delle applicazioni più interessanti consiste nel cambiare in pipe i file con un certo nome. Ad esempio, per auto-elaborare file compressi con gzip o compress utilizzando gzip: @ARGV = map { /^\.(gz|Z)$/ ? "gzip -dc $_ |" : $_ } @ARGV; O anche, se avete il programma GET installato dal modulo LWP, potete scaricare dalle URL prima di elaborarle: @ARGV = map { m#^\w+://# ? "GET $_ |" : $_ } @ARGV; Non a caso viene chiamata
Open à la CSe volete la convenienza della shell, allora la funzione
sysopen HANDLE, PERCORSO, OPZIONI, [MASCHERA] Il parametro Sebbene i valori tradizionali di sola-lettura, sola-scrittura e lettura-scrittura siano, rispettivamente, 0, 1 e 2, ciò non è vero su tutti i sistemi. È meglio, piuttosto, caricare le costanti giuste dal modulo Fcntl, che fornisce le seguenti opzioni standard: O_RDONLY Sola lettura O_WRONLY Sola scrittura O_RDWR Lettura e scrittura O_CREAT Crea il file se non esiste O_EXCL Fallisce se il file esiste O_APPEND Aggiunge al file O_TRUNC Tronca il file O_NONBLOCK Accesso non bloccante Alcune opzioni meno comuni che sono talvolta disponibili in alcuni
sistemi operativi includono Ecco un esempio di come utilizzare Per aprire un file in lettura: open(FH, "< $percorso"); sysopen(FH, $percorso, O_RDONLY); Per aprire un file in scrittura, creando un file nuovo se necessario o altrimenti troncando un file pre-esistente: open(FH, "> $percorso"); sysopen(FH, $percorso, O_WRONLY | O_TRUNC | O_CREAT); Per aprire un file per aggiungere alla fine, creandolo se necessario: open(FH, ">> $percorso"); sysopen(FH, $percorso, O_WRONLY | O_APPEND | O_CREAT); Per aprire un file per aggiornamento, laddove il file deve necessariamente esistere: open(FH, "+< $percorso"); sysopen(FH, $percorso, O_RDWR); Quelle che seguono, invece, sono le cose che potete fare con Per aprire un file in scrittura, creando un nuovo file che non deve esistere precedentemente: sysopen(FH, $percorso, O_WRONLY | O_EXCL | O_CREAT); Per aprire un file in aggiunta, laddove il file deve già esistere: sysopen(FH, $percorso, O_WRONLY | O_APPEND); Per aprire un file per aggiornamento, creando un nuovo file se necessario: sysopen(FH, $percorso, O_RDWR | O_CREAT); Per aprire un file per aggiornamento, laddove il file non deve già esistere: sysopen(FH, $percorso, O_RDWR | O_EXCL | O_CREAT); Per aprire un file in modalità non bloccante, creandone uno se necessario: sysopen(FH, $percorso, O_WRONLY | O_NONBLOCK | O_CREAT);
Permessi à la modeSe omettete l'argomento Perché così permissivo? Beh, in realtà non è
proprio così. La Ad esempio, se la vostra Dovreste aver bisogno di usare l'argomento
Oscuri Trucchi di Apertura
Ri-Aprire File (duplicati)A volte avete già un filehandle aperto, e volete un altro handle che
ne sia un duplicato. Nella shell, mettiamo un carattere ``&'' immediatamente
prima del numero del descrittore di file in fase di redirezione. Ad
esempio, open(SALVAOUT, ">&SALVAERR") || die "impossibile duplicare SALVAERR: $!"; open(MHCONTEXT, "<&4") || die "impossibile duplicare fd4: $!"; Questo significa che se una funzione si aspetta di ricevere un nome di file, ma non volete fornirlo perché il file in questione è già aperto, potete passare semplicemente il filehandle precedendolo con un carattere ``&''. In ogni caso, è meglio utilizzare un handle pienamente qualificato, per tenere in conto il caso che la funzione si trovi in un package differente: una_qualche_funzione("&main::LOGFILE"); In questo modo, se Se avete uno di quegli oggetti I/O strani ed avveniristici di cui la gente
di C++ blatera tanto, questo approccio non funziona perché non sono
dei filehandle nativi veri e propri. In questo caso dovete
utilizzare use IO::Socket; $handle = IO::Socket::INET->new("www.perl.com:80"); $fd = $handle->fileno; una_qualche_funzione("&$fd"); # non una chiamata indiretta di funzione Può risultare più semplice (e di sicuro più veloce) usare semplicemente filehandle reali: use IO::Socket; local *REMOTO = IO::Socket::INET->new("www.perl.com:80"); die "impossibile connettersi" unless defined(fileno(REMOTO)); una_qualche_funzione("&main::REMOTO"); Se il filehandle o il numero di descrittore sono preceduti da una
combinazione ``&='' piuttosto che da un semplice ``&'', Perl non creerà un
descrittore aperto completamente nuovo utilizzando la chiamata di
sistema $fd = $ENV{"MHCONTEXTFD"}; open(MHCONTEXT, "<&=$fd") or die "errore di fdopen $fd: $!"; Se state utilizzando l'input magico
Fugare il DweomerPerl è un linguaggio più DWIMmico di altri tipo Java -- laddove DWIM è un acronimo per ``do what I mean'' [letteralmente ``fa quello che intendo'', ossia cerca di capire le mie reali intenzioni da solo, N.d.T.]. Ma questo principio a volte porta ad un quantitativo di magia nascosta superiore a quella che uno sa di poter utilizzare. In questo senso, Perl è anche i<dweomer>, una parola arcana che indica un sortilegio [Wikipedia: oggetto magico o magia prodotta dallo stesso, N.d.T.]. A volte, la DWIMmicità di Perl assomiglia un po' troppo ad un dweomer perché ci si possa sentire a posto. Se la $file =~ s#^(\s)#./$1#; open(FH, "< $file\0") || die "impossibile aprire $file: $!"; Si assume, chiaramente, che il vostro sistema consideri ``.'' la
directory di lavoro corrente, ``/'' il separatore delle directory,
e che non ammetta degli ASCII NUL come carattere valido in un nome di file.
La maggior parte dei sistemi si adattano a questa convenzione, inclusi
tutti i sistemi POSIX così come i sistemi proprietari Microsoft.
L'unico sistema vagamente popolare che non funziona in questo modo
è il sistema Macintosh ``Classic'', che utilizza ``:'' laddove il resto delle
persone utilizza ``/''. Forse Se volete utilizzare l'elaborazione di # "Sam si sedette a terra e si prese la testa fra le mani. # 'Vorrei non essere mai venuto qui, e non voglio vedere # altra magia', disse, e sprofondo` nel silenzio." for (@ARGV) { s#^([^./])#./$1#; $_ .= "\0"; } while (<>) { # ora si elabora $_ } Ma attenzione che gli utenti non apprezzeranno il fatto di non poter utilizzare ``-'' per intendere l'input standard, per una convenzione standard.
Percorsi come ApertureAvrete probabilmente notato che le funzioni Un qualche warning at scriptname line 29, <FH> line 7. Questo è possibile perché avete aperto un filehandle FH, e ci avete letto sette record. Ma qual era il nome del file, invece che l'handle? Se non state lavorando con open($path, "< $path") || die "impossibile aprire $path: $!"; while (<$path>) { # quello che serve } Visto che state utilizzando il percorso al file come handle, otterrete dei messaggi più simili a Un qualche warning at scriptname line 29, </etc/motd> line 7.
Apertura a Parametro SingoloVi ricordate quando abbiamo detto che la $FILE = "/etc/motd"; open FILE or die "impossibile aprire $FILE: $!"; while (<FILE>) { # quello che serve } Perché tutto questo? Qualcuno deve fare i conti con le consuetudini. È qualcosa che è stato presente in Perl dall'inizio, se non prima.
Giocare con STDIN e STDOUTUna mossa intelligente da fare con STDOUT è chiuderlo esplicitamente quando il programma termina. END { close(STDOUT) || die "impossibile chiudere stdout: $!" } Se non lo fate, ed il vostro programma riempie la partizione del disco per una redirezione della riga di comando, non vi segnalerà l'errore di uscita con uno stato di errore. Non siete obbligati a piegarvi agli STDIN e STDOUT che vi vengono dati. Siete liberi di riaprirli a vostro piacimento. open(STDIN, "< datafile") || die "impossibile aprire datafile: $!"; open(STDOUT, "> output") || die "impossibile aprire output: $!"; In seguito, essi verranno utilizzati direttamente o passati ai sottoprocessi. È come se il programma fosse stato chiamato con queste redirezioni direttamente dalla linea di comando. Probabilmente è più interessante per connettersi alle pipe. Ad esempio: $paginatore = $ENV{PAGER} || "(less || more)"; open(STDOUT, "| $paginatore") || die "impossibile invocare un paginatore: $!"; Ciò fa sì che sembri che il vostro programma sia stato chiamato con
il suo output standard rediretto già sul vostro programma di paginazione.
Potete anche utilizzare questo approccio in congiunzione con una prime_righe(100); while (<>) { print; } sub prime_righe { my $righe = shift || 20; return if $pid = open(STDOUT, "|-"); # esci se processo padre die "errore in fork: $!" unless defined $pid; while (<STDIN>) { last if --$lines < 0; print; } exit; } Questa tecnica può essere applicata per inserire quanti filtri volete nel vostro stream di uscita.
Altre Questioni di I/OGli argomenti che seguono non riguardano esattamente
Aprire File che Non-Sono-FileQuand'è che un file non è un file? Beh, potreste dire quando esiste ma non è un file puro e semplice. Controlliamo se è un collegamento simbolico prima di tutto, tanto per sicurezza. if (-l $file || ! -f _) { print "$file non un file semplice\n"; } Quali altri tipi di file ci sono oltre, ehm, i file? Le directory, i
collegamenti simbolici, pipe con nome, socket Unix e dispositivi
a blocchi ed a caratteri. Questi sono tutti file -- solo che non sono
file semplici. Non è lo stesso problema del fatto che sia un file
di testo o meno. Non tutti i file di solo testo sono file semplici.
Come non tutti i file semplici sono file di solo testo. Ecco perché ci
sono due test Per aprire una directory, dovreste utilizzare la funzione opendir(DIR, $nomedir) or die "errore di opendir su $nomedir: $!"; while (defined($file = readdir(DIR))) { # utilizza "$nomedir/$file" } closedir(DIR); Se volete accedere ricorsivamente alle directory, è meglio utilizzare il modulo File::Find. L'esempio che segue stampa ricorsivamente tutti i file ed aggiunge un carattere ``/'' se il file è una directory. @ARGV = qw(.) unless @ARGV; use File::Find; find sub { print $File::Find::name, -d && '/', "\n" }, @ARGV; Quest'altro trova tutti i collegamenti simbolici fasulli nell'albero, al di sotto di una determinata directory: find sub { print "$File::Find::name\n" if -l && !-e }, $dir; Come potete vedere, con i collegamenti simbolici potete semplicemente
far finta che si tratti del file a cui stanno puntando. O, se
volete sapere a cosa sta puntando un collegamento, allora entra
in gioco if (-l $file) { if (defined($dove = readlink($file))) { print "$file punta a $dove\n"; } else { print "$file non punta da nessuna parte: $!\n"; } }
Aprire Pipe con NomeLe pipe con nome sono un'altra faccenda. Basta far finta che si tratti di file regolari, ricordando però che le aperture sono normalmente bloccanti finché non ci siano sia un lettore che uno scrittore. Potete leggere di più sull'argomento in perlipc/``Pipe con nome''. I socket Unix sono delle bestie piuttosto differenti; sono descritti in perlipc/``Client e Server TCP nel Dominio Unix''. Quando si tratta di aprire dispositivi, può essere sia facile che complicato. Assumeremo che se state aprendo un dispositivo a blocchi sappiate quello che state facendo. I dispositivi a caratteri sono più interessanti. Tipicamente sono utilizzati per i modem, i mouse e qualche tipo di stampante. Il tutto è descritto in perlfaq8/``Come leggo e scrivo su una porta seriale?''. Spesso è sufficiente aprirli con una certa cautela: sysopen(TTYIN, "/dev/ttyS1", O_RDWR | O_NDELAY | O_NOCTTY) # (O_NOCTTY non e` piu` necessario nei sistemi POSIX) or die "errore open /dev/ttyS1: $!"; open(TTYOUT, "+>&TTYIN") or die "errore dup TTYIN: $!"; $ofh = select(TTYOUT); $| = 1; select($ofh); print TTYOUT "+++at\015"; $risposta = <TTYIN>; Riguardo ai descrittori che non avete aperto con use Fcntl; my $vecchi_indicatori = fcntl($handle, F_GETFL, 0) or die "impossibile ottenere la configurazione attuale: $!"; fcntl($handle, F_SETFL, $vecchi_indicatori | O_NONBLOCK) or die "impossibile impostare come non bloccante: $!"; Piuttosto che perdervi in una palude di
Aprire SocketChe altro potete aprire? Per aprire una connessione utilizzando i socket,
non potete utilizzare una delle due funzioni use IO::Socket; local *FH = IO::Socket::INET->new("www.perl.com:80"); Per aprire una URL, il dottore ordina i moduli LWP presenti su CPAN. Non c'è alcuna interfaccia tipo filehandle, ma è comunque facile ottenere il contenuto di un documento: use LWP::Simple; $doc = get('http://www.linpro.no/lwp/');
File BinariSu certi sistemi più obsoleti con modelli di I/O che si potrebbero pietosamente chiamare convoluti in fase terminale (altri direbbero rotti), un file non è un file -- almeno per quanto riguarda la libreria I/O standard di C. Su questi vecchi sistemi le cui librerie (ma non i kernel) fanno distinzione fra stream di testo e stream binari, per far sì che i file si comportino a modo, avrebbe bisogno di piegarvi al passato per evitare fastidiosi problemi. In tali sistemi infelici, i socket e le pipe sono già aperti in modalità binaria, e non c'è al momento alcun modo per evitarlo. Con i file, avete più opzioni. Un'altra opzione consiste nell'utilizzare la funzione binmode(STDIN); binmode(STDOUT); while (<STDIN>) { print } Si può anche passare un'opzione non standard a sysopen(BINDAT, "record.dati", O_RDWR | O_BINARY) || die "impossible aprire record.dati: $!"; Ora potete utilizzare Su sistemi con sistemi di I/O esotici, si dà il caso che, abbastanza
stupefacentemente, persino l'I/O non bufferizzato utilizzando while (sysread(WHENCE, $buf, 1024)) { syswrite(WHITHER, $buf, length($buf)); } Dipendentemente dalle vicissitudini del vostro sistema a runtime, persino
queste chiamate potrebbero aver bisogno di
Blocco di un FileIn un ambiente multitasking [ossia, in grado di eseguire più compiti alla volta, N.d.T.] potreste aver bisogno di fare attenzione a non scontrarvi con altri processi che vogliono effettuare I/O sugli stessi file su cui state lavorando. Avrete spesso bisogno di lock [blocchi, nel senso del verbo bloccare, N.d.T.] condivisi o esclusivi sui file per leggere e scrivere, rispettivamente. Potreste anche far finta che esistano solo lock esclusivi. Non utilizzate mai il test di esistenza di un file L'interfaccia di blocco più portabile in Perl è attraverso la funzione
Il lock di un file non impedisce ad un altro processo di fare I/O. Un lock di un file semplicemente blocca altri nel tentativo di ottenere un lock stesso, non i processi che provano a fare I/O. Poiché il rispetto di questi lock non è tassativo, se un processo utilizza questo meccanismo ed un altro no, tutti gli schemi saltano. Per default, la chiamata a Ecco come ottenere un lock condiviso bloccante su un file, tipicamente utilizzato per la lettura: use 5.004; use Fcntl qw(:DEFAULT :flock); open(FH, "< nomefile") or die "impossibile aprire nomefile: $!"; flock(FH, LOCK_SH) or die "impossibile bloccare nomefile: $!"; # ora leggi da FH Potete ottenere un lock non bloccante utilizzando flock(FH, LOCK_SH | LOCK_NB) or die "impossibile bloccare nomefile: $!"; Ciò può essere utile per ottenere un comportamento più gentile con l'utente avvisando che state per bloccare: use 5.004; use Fcntl qw(:DEFAULT :flock); open(FH, "< nomefile") or die "impossibile aprire nomefile: $!"; unless (flock(FH, LOCK_SH | LOCK_NB)) { $| = 1; print "Aspetto il lock..."; flock(FH, LOCK_SH) or die "impossibile bloccare nomefile: $!"; print "preso.\n" } # ora leggi da FH Per ottenere un lock esclusivo, tipicamente utilizzato in scrittura,
dovete prestare attenzione. Effettuiamo una use 5.004; use Fcntl qw(:DEFAULT :flock); sysopen(FH, "nomefile", O_WRONLY | O_CREAT) or die "impossibile aprire nomefile: $!"; flock(FH, LOCK_EX) or die "impossibile bloccare nomefile: $!"; truncate(FH, 0) or die "impossibile troncare nomefile: $!"; # ora scrivi su FH Infine, per colpa di quei milioni che non possono essere distolti dal perdere cicli CPU su quei dispositivi di inutile vanità chiamati contatori di richieste di pagine web, ecco come incrementare un numero in un file in maniera sicura: use Fcntl qw(:DEFAULT :flock); sysopen(FH, "numfile", O_RDWR | O_CREAT) or die "impossibile aprire numfile: $!"; # autoflush FH $ofh = select(FH); $| = 1; select ($ofh); flock(FH, LOCK_EX) or die "impossibile bloccare numfile per la scrittura: $!"; $num = <FH> || 0; seek(FH, 0, 0) or die "impossibile tornare all'inizio di numfile : $!"; print FH $num+1, "\n" or die "impossibile scrivere numfile: $!"; truncate(FH, tell(FH)) or die "errore di truncate su numfile: $!"; close(FH) or die "impossibile chiudere numfile: $!";
Strati IOIn Perl 5.8.0 è stato introdotto un nuovo ambiente di I/O chiamato ``PerlIO''. Si tratta di un nuovo ``sistema idrico'' per la gestione di tutto l'I/O in Perl; nella maggior parte dei casi funzionerà tutto come prima, ma PerlIO introduce anche nuove caratteristiche come la possibilità di pensare l'I/O come una serie di ``strati''. Uno strato I/O può, oltre al semplice spostamento dei dati, effettuarvi delle trasformazioni. Queste trasformazioni includono compressione e decompressione, crittazione e decrittazione e la trasformazione fra le varie codifiche dei caratteri. Una discussione approfondita sulle caratteristiche di PerlIO è fuori dagli obiettivi di questo tutorial, ma ecco come riconoscere gli strati in uso:
Per una discussione più dettagliata su PerlIO consultate PerlIO; per una discussione più dettagliata su Unicode e I/O consultate perluniintro.
CONSULTATE ANCHELe funzioni
AUTORE e COPYRIGHTCopyright 1998 Tom Christiansen. This documentation is free; you can redistribute it and/or modify it under the same terms as Perl itself. Irrespective of its distribution, all code examples in these files are hereby placed into the public domain. You are permitted and encouraged to use this code in your own programs for fun or for profit as you see fit. A simple comment in the code giving credit would be courteous but is not required. [Le note di copyright sono usualmente valide solo nella lingua originale, viste le implicazioni legali. Il testo corrisponde grosso modo a quanto segue: Questa documentazione e` libera; potete ridistribuirla e/o modificarla sotto gli stessi termini di Perl stesso. Indipendentemente dalla sua distribuzione, tutti i codici di esempio in questi file sono qui posti nel pubblico dominio. Vi e` consentito, e siete anzi incoraggiati a farlo, utilizzare questo codice nei vostri propri programmi per divertimento o per profitto, come vi sembra meglio. Un semplice commento nel codice per dare credito sarebbe cortese ma non e` richiesto. N.d.T.]
STORIAPrima release: Sabato 9 Gennaio 1999, 08:09:11 MST
TRADUZIONE
VersioneLa versione su cui si basa questa traduzione è ottenibile con: perl -MPOD2::IT -e print_pod perlopentut Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .
TraduttoreTraduzione a cura di Flavio Poletti.
RevisoreRevisione a cura di dree. Mon Jun 11 22:02:18 2012 |