|
|||
print "Dime tu nombre: " nombre = gets |
Kernel (gets,
open, print, printf, putc,
puts, readline, readlines, y
test) que hacen fácil y conveniente escribir programas claros en
Ruby. Normalmente estos métodos hacen la E/S por la entrada y salida
estándares, lo que resulta útil para escribir filtros. Están documentados a
partir de la página 411.
La segunda manera, que te da mucho más control, es usar objetos
IO.
IO, para gestionar
toda la entrada y salida.
De esta clase base heredan File y
BasicSocket, para dar un comportamiento más
especializado, pero los principìos se mantienen iguales para todos. Un objeto
IO es un canal bidireccional entre un programa en Ruby
y un recurso externo[Para aquellos que tienen que saber por fuerza
los detalles de implementación, significa que un solo objeto
IO puede estar gestionando más de un descriptor del
sistema operativo. Por ejemplo, cuando abres una pareja de tuberías, un solo
objeto IO contiene tanto la de lectura como la de
escritura].
Puede que haya más de lo que parece en los objetos IO,
pero al final simplemente leerás de y escribirás en él.
En este capítulo nos concentraremos en la clase IO y en
su clase heredera más común, File. Para más detalles
sobre las clases relacionadas con la red, vea el apartado que empieza en la
página 469.
File.new
.
unFichero = File.new("ficheroprueba", "r")
# ... procesar el fichero
unFichero.close
|
File preparado para
leer, escribir o ambas, según los caracteres de modo que elijas (aquí abrimos
``ficheroprueba'' para leer con el ``r''). La lista completa
de modos permitidos está en la página 326. También puedes, optativamente,
elegir los permisos del fichero a la hora de crearlo; mira la descripción de
File.new
en la página 303 para más detalles. Después de abrir el fichero podemos
trabajar con él, leyendo o escribiendo lo que queramos. Por último, como
responsables programadores, cerramos el fichero para asegurarnos de que todos
los datos que hay en memoria se escriben y que todos los recursos relacionados
se liberan.
Pero aquí Ruby puede hacerte la vida un poco más fácil. El método
File.open
también abre un fichero. En su uso normal, hace lo mismo que
File.new
.
Sin embargo, si hay un bloque asociado a la llamada, open se
comporta de manera diferente: en vez de devolver un nuevo objeto
File, invoca al bloque, pasándole el fichero acabado de
abrir como parámetro. Cuando el bloque termina, el fichero se cierra
automáticamente.
File.open("ficheroprueba", "r") do |unFich|
# ... procesar el fichero
end
|
gets lee
una línea de la entrada de la terminal, y unFich.gets lee una línea
del objeto fichero unFich.
Sin embargo, los objetos de E/S tienen una serie de métodos de acceso
adicionales, pensados para hacer nuestra vida más fácil.
IO, puedes usar varios iteradores de Ruby.
IO#each_byte
invoca un bloque para el siguiente byte de 8 bits del objeto
IO (en este caso, del objeto
File).
unFich = File.new("ficheroprueba")
unFich.each_byte {|c| putc c; putc ?. }
|
É.s.t.a. .e.s. .l.a. .l.í.n.e.a. .u.n.o. .É.s.t.a. .e.s. .l.a. .l.í.n.e.a. .d.o.s. .É.s.t.a. .e.s. .l.a. .l.í.n.e.a. .t.r.e.s. .Y. .a.s.í. .s.i.e.m.p.r.e....... . |
IO#each_line
llama al bloque con la siguiente línea del fichero.
En el siguiente ejemplo haremos visibles los saltos de línea usando
String#dump
, para que puedas ver que no estamos haciendo trampas.
unFich.each_line {|linea| puts "Obtengo #{linea.dump}" }
|
Obtengo "\311sta es la l\355nea uno\n" Obtengo "\311sta es la l\355nea dos\n" Obtengo "\311sta es la l\355nea tres\n" Obtengo "Y as\355 siempre...\n" |
each_line cualquier serie de caracteres como
separador de línea, y partirá la entrada adecuadamente, devolviendo el
separador de líneas al final de cada línea de datos. De ahí que veas los
``\n'' en la salida del anterior ejemplo. En el siguiente usaremos
``e'' como separador de líneas.
unFich.each_line("e") do |linea|
puts "Obtengo #{ linea.dump }"
end
|
Obtengo "\311sta e" Obtengo "s la l\355ne" Obtengo "a uno\n\311sta e" Obtengo "s la l\355ne" Obtengo "a dos\n\311sta e" Obtengo "s la l\355ne" Obtengo "a tre" Obtengo "s\nY as\355 sie" Obtengo "mpre" Obtengo "...\n" |
IO.foreach
.
Este método recibe el nombre de una fuente de E/S, la abre en modo lectura,
llama al iterador por cada línea del fichero, y entonces lo cierra
automáticamente.
IO.foreach("ficheroprueba") { |line| puts line }
|
Ésta es la línea uno Ésta es la línea dos Ésta es la línea tres Y así siempre... |
lista = IO.readlines("ficheroprueba")
|
||
lista.length
|
» |
4
|
lista[0]
|
» |
"\311sta es la l\355nea uno\n"
|
puts y
print, pasándoles cualquier objeto y confiando en que Ruby hará
lo correcto (que, por supuesto, hace). ¿Pero qué está haciendo
exactamente?
La respuesta es bastante simple. Con un par de excepciones, cada objeto que
pasas a puts y print se convierte a caracteres
llamando al método to_s del propio objeto. Si por cualquier razón
el método no devuelve una ristra de caracteres válida, se crea una, incluyendo
el nombre de la clase y el id del objeto, algo como
<NombreClase:0x123456>.
Las excepciones también son simples. El objeto nil se imprime como la
ristra ``nil'', y una lista pasada a puts se escribirá como si
se llamara al método con cada uno de sus elementos por separado.
¿Y qué pasa si quieres escribir datos binarios y no quieres que Ruby esté
cambiando nada? Normalmente puedes usar
IO#print
y pasar una ristras con los caracteres a escribir. Sin embargo, puedes llegar
a las rutinas de E/S de nivel bajo si de verdad quieres---mira la
documentación de
IO#sysread
y
IO#syswrite
en la página 335.
¿Y cómo metes tus datos binarios en una ristra, para empezar? Las dos maneras
más comunes son tratarlo byte a byte o usar
Array#pack
.
str = ""
|
» |
""
|
str << 1 << 2 << 3
|
» |
"\001\002\003"
|
|
||
[ 4, 5, 6 ].pack("c*")
|
» |
"\004\005\006"
|
Array con el operador
<<, también puedes añadir un objeto a un flujo
IO de salida:
endl = "\n" $stdout << 99 << " globos rojos" << endl |
99 globos rojos |
<< usa el to_s para
convertir sus argumentos en caracteres antes de enviarlos por su camino.
require 'socket'
cliente = TCPSocket.open('localhost', 'finger')
cliente.send("oracle\n", 0) # 0 means standard packet
puts cliente.readlines
cliente.close
|
Login: oracle Name: Oracle installation Directory: /home/oracle Shell: /bin/bash Never logged in. No Mail. No Plan. |
require 'net/http'
h = Net::HTTP.new('www.pragmaticprogrammer.com', 80)
resp, datos = h.get('/index.html', nil)
if resp.message == "OK"
datos.scan(/<img src="(.*?)"/) { |x| puts x }
end
|
images/title_main.gif images/dot.gif images/dot.gif images/dot.gif images/aafounders_70.jpg images/pp_cover_thumb.png images/ruby_cover_thumb.png images/dot.gif images/dot.gif |