[Lugge] Re: Traduzione 'Programming Ruby' - 2002.08.13

  • From: Giuliano <bipieffe@xxxxxxxx>
  • To: lugge@xxxxxxxxxxxxx
  • Date: Sun, 18 Aug 2002 21:33:00 +0200

Massimo,
guarda un po' se questo può andare?
Rimango convinto che vi possa essere di grande aiuto, uso amaya per la
verifica finale, ma così sorveglio di non cassare qualche tag!
Allego tut_io.
Segue a breve tut_threads.
Ciao
Giuliano

Massimo Arnaudo wrote:

> Ciao,
> grazie delle note, provvederò quanto prima a modificare il testo
> esistente.
>
> Massimo
> --
> E impari che puoi davvero sopportare,
> che sei davvero forte,
> e che vali davvero.
> ---             ---
> HomePage:       http://spazioinwind.iol.it/arnaudo
> LinuxGroup:     http://lugge.ziobudda.net
> <========----------
>
>  Prima di scrivere in m-list per favore leggi il regolamento
>  http://www.lugge.net/soci/manifesto.htm#list
>
>  Archivio delle e-mail postate in lista
>  http://www.freelists.org/archives/lugge/
>
> ----------========>
>
>
Title: Programming Ruby: The Pragmatic Programmer's Guide

Programming Ruby

The Pragmatic Programmer's Guide

Previous < Contents ^
Next >

Basic Input and Output



Ruby dispone di ciò che a prima vista appare come due gruppi separati di routines di I/O. La prima è la semplice interfaccia ---la abbiamo utilizzata pressochè esclusivamente sino ad ora.

print "Enter your name: "
name = gets

Ci sono alcuni gruppi di metodi relativi all'I/O implementati nel modulo Kernel---gets, open, print, printf, putc, puts, readline, readlines, e test---che rendono semplice e conveniente scrivere direttamente programmi Ruby. Questi metodi gestiscono I/O dallo standard input allo standard output, che li rende utili come filtri di scrittura. La relativa documentazione parte da pag. 411.

Il secondo modo, che vi consente più controllo, è usare gli oggetti I/O.

What Is an IO Object?

Ruby definisce una sola classe di base, I/O, per maneggiare input ed output.. Questa classe di base è suddivisa in sottoclassi da classi File e BasicSocket per avere una conoscenza più approfondita, ma i principi danno gli stessi risultati. Un oggetto I/O è un canale bidirezionale tra un programma Ruby ed una risorsa esterna. [Per coloro che debbano appena conoscere i dettagli di implementazione ciò significa che un solo oggetto I/O possa talvolta gestire più di un descrittore di file di sistema operativo. Ad esempio se si aprono un paio di pipes un solo oggetto I/O> contiene sia una pipe in lettura che una pipe in scrittura.] Ci potrebbe essere più di un oggetto I/O che incontri l'occhio, ma alla fine voi potete appena semplicemente scrivere in esso e leggere da esso.

In questo capitolo ci concentreremo sulla classe I/O e sulla sua più comunemente usata sottoclasse, la classe File.Per avere maggiori dettagli circa l'uso delle calssi socket per il lavoro di rete vedere la sezione che inizia da pag. 469.

Opening and Closing Files

Come ci si potrebbe aspettare potreste creare un nuovo oggetto file usando File.new .

aFile = File.new("testfile", "r")

# ... process the file

aFile.close

+
Si può creare un oggetto File che sia aperto in lettura, scrittura od entrambe, in armonia col modo string (qui si è aperto ``testfile'' per la lettura con un ``r''). La lista completa dei modi ammissibili appare a pag. 326. Si può anche opzionalmente specificare i permessi del file quando si crea un file; guardare la descrizione di File.new a pag. 303 per i dettagli. Dopo avere aperto il file si può lavorare con esso, scrivendo e/o leggendo i dati se necessario. In ultimo, da responsabile del software cittadino, si chiuda il file, accertandosi che tutti i dati presenti nel buffer siano stati salvati e che le relative risorse siano state liberate.

Ma qui Ruby può rendervi la vita un po' più facile. Il metodo File.open così apre un file. Nell'utilizzo regolare esso si comporta proprio come File.new . Comunque se vi fosse un blocco associato con la chiamata, open si comporterebbe in modo diverso.Invece di ritornare un nuovo oggetto File esso invocherebbe il blocco, passando il nuovamente aperto File come fosse un parametro. All'uscita del blocco il file verrebbe automaticamente chiuso.

File.open("testfile", "r") do |aFile|

# ... process the file

end

Reading and Writing Files

Gli stessi metodi che abbiamo impiegato per il ``semplice'' I/O possono essere impiegati per tutti gli oggetti file. Così gets legge una riga dallo standard input, e aFile.gets legge una riga dall'oggetto file aFile.

Comunque gli oggetti I/O prevedono un ulteriore gruppo di metodi d'accesso, tutti intesi per semplificarvi la vita.

Iterators for Reading

Alla stessa maniera con cui si impiegano i soliti cicli per leggere dati da un flusso di IO, si possono impiegare anche diversi iteratori di Ruby. IO#each_byte invoca un blocco con i successivi byte di 8-bit dall'oggetto IO (in questo caso un oggetto di tipo File).

aFile = File.new("testfile")
aFile.each_byte {|ch| putc ch; putc ?. }
produces:
T.h.i.s. .i.s. .l.i.n.e. .o.n.e.
.T.h.i.s. .i.s. .l.i.n.e. .t.w.o.
.T.h.i.s. .i.s. .l.i.n.e. .t.h.r.e.e.
.A.n.d. .s.o. .o.n.......
.

IO#each_line chiama il blocco con la linea successiva dal file. Nell'esempio che segue renderemo visibili le originali newlines usando String#dump , così si potrà constatare che non stiamo parlando a vanvera.

aFile.each_line {|line| puts "Got #{line.dump}" }
produces:
Got "This is line one\n"
Got "This is line two\n"
Got "This is line three\n"
Got "And so on...\n"

Si può passare each_line a qualunque sequenza di caratteri come separatore di linea ed esso interromperà di conseguenza l'input, ritornando il fine linea alla fine di ogni linea di dati. Questa è la ragione per cui si vedono i caratteri ``\n'' nell'output dell'esempio precedente. Nel prossimo esempio verrà impiegato ``e'' come separatore di linea.

aFile.each_line("e") do |line|
  puts "Got #{ line.dump }"
end
produces:
Got "This is line"
Got " one"
Got "\nThis is line"
Got " two\nThis is line"
Got " thre"
Got "e"
Got "\nAnd so on...\n"

Se si mette insieme l'idea di iteratore con la possibilità dell'auto chiusura di un blocco si ottiene IO.foreach . Questo metodo prende il nome da un sorgente di I/O, lo apre per leggerlo, chiama l'iteratore una volta per ogni linea del file ed infine chiude il file automaticamente.

IO.foreach("testfile") { |line| puts line }
produces:
This is line one
This is line two
This is line three
And so on...

O, se si preferisce si può ricondurre un intero file entro un array di linee:

arr = IO.readlines("testfile")
arr.length » 4
arr[0] » "This is line one\n"

Non si creda che I/O non sia mai certo in una parola incerta---le eccezioni possono essere causa dei più tanti errori e si dovrebbe essere pronti ad intercettarli ed eseguire le azioni opportune.

Writing to Files

Così, fino ad adesso, abbiamo tranquillamente chiamato puts e print, passando per tutti i vecchi oggetti e credendo che Ruby avrebbe fatto la cosa giusta (ove, naturalmente, ciò possa avvenire). Ma che cosa starà esattamente facendo?

La risposta è gradevolmente semplice. Con un paio di eccezioni ogni oggetto venga passato a puts ed a print viene convertito in una stringa chiamando questo metodo relativo all'oggetto to_s. Se per qualunque motivo il metodo to_s non dovesse ritornare una stringa valida, verrebbe creata una stringa contenente nome ed id della classe inerente l'oggetto, qualcosa come <ClassName:0x123456>.

Le eccezioni sono sin troppo semplici. L'oggetto nil verrà stampato come la stringa ``nil,'' ed un array passato a puts verrà scritto come se ognuno dei propri elementi consecutivi venisse passato separatamente a puts.

Che fare se si vogliono scrivere dati binari e non si vuole che Ruby si nutra con cio?. Bene, normalmente si potrebbe semplicemente usare IO#print e passarli entro una stringa contenente i bytes che debbono essere scritti. Comunque si può ricorrere alle routines di basso livello di input ed output, se davvero si volesse farlo---dare un'occhiata alla documentazione per IO#sysread and IO#syswrite a pag. 335.

E come si fa a porre i dati binari al primo posto entro una stringa? Le due strade più semplici sono di inserirli ad uno per volta od usare Array#pack .

str = "" » ""
str << 1 << 2 << 3 » "\001\002\003"
[ 4, 5, 6 ].pack("c*") » "\004\005\006"

But I Miss My C++ Iostream

Talvolta non c'è proprio la voglia di provare...Comunque proprio come si può aggiungere un oggetto ad un Array usando l'operatore <<, si può altrettanto aggiungere un oggetto ad un flusso di output IO:

endl = "\n"
$stdout << 99 << " red balloons" << endl
produces:
99 red balloons

Inoltre il metodo << utilizza to_s per convertire i propri argomenti in stringhe prima di inviarli alla loro giusta destinazione.

Talking to Networks

Ruby è versatile nel maggior numero di protocolli Internet, sia a basso che ad alto livello.

Per coloro che si divertono a strisciare attorno al livello di rete, Ruby provvede con una serie di classi nella libreria dei socket (documentata a partire da pag. 469). Queste classi vi danno accesso ai socket di dominio TCP, UDP, SOCKS, ed Unix, allo stesso modo che ad ogni altro socket aggiuntivo supportato nella vostra architettura. La libreria fornisce anche classi per rendere più agevole la scrittura di servers. Ecco un semplice programma che ottiene informazioni circa l'utente ``oracle'' sulla macchina locale, usando il protocollo finger.

require 'socket'
client = TCPSocket.open('localhost', 'finger')
client.send("oracle\n", 0)    # 0 means standard packet
puts client.readlines
client.close
produce:
Login: oracle                                 Name: Oracle installation
Directory: /home/oracle                     Shell: /bin/bash
Never logged in.
No Mail.
No Plan.

Ad un livello più alto il gruppo di moduli di libreria lib/net fornisce gli strumenti per manipolare alcuni protocolli di application-level (comunemente FTP, HTTP, POP, SMTP, e telnet). Ciò viene documentato a aprtire da pag. 482. Per esempio, il programma che segue elenca le immagini mostrate nella home page del Pragmatic Programmer.

require 'net/http'

h = Net::HTTP.new('www.pragmaticprogrammer.com', 80)
resp, data = h.get('/index.html', nil)
if resp.message == "OK"
  data.scan(/<img src=""/) { |x| puts x }
end
produces:
images/title_main.gif
images/dot.gif
images/dot.gif
images/dot.gif
images/AgileAllianceSmall.jpg
images/dot.gif
images/dot.gif


Previous < Contents ^
Next >

Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright © 2000 Addison Wesley Longman, Inc. Released under the terms of the Open Publication License V1.0.
This reference is available for download.

Other related posts: