|
|||
print "Geben Sie Ihren Namen ein: " name = gets |
Kernel
sind eine Menge I/O-bezogene Methoden
implementiert -- gets
, open
, printf
,
putc
, puts
, readline
,
readlines
und test
--, mit deren Hilfe man einfach
und bequem einfache Ruby-Programme schreiben kann.
Diese Methoden arbeiten typischerweise mit der Standardeingabe und der
Standardausgabe, womit sie nützlich zum Schreiben von Filtern sind.
Sie finden Sie ab Seite 415 beschrieben.
Der zweite Weg, der Ihnen viel mehr Kontrolle gibt, ist,
IO
-Objekte zu benutzen.
IO
, die Ein-
und Ausgabe behandelt.
Diese Klasse wird von File
und
BasicSocket
, die spezialisierteres Verhalten
bereitstellen, geerbt, die Prinzipien sind dennoch immer die gleichen.
Ein IO
-Objekt ist ein in beide Richtungen arbeitender
Kanal zwischen einem Ruby-Programm und einer externene
Ressource.[Für die, die Details der Implementierung einfach wissen
müssen: Das bedeutet, dass ein einzelnes IO
-Objekt
manchmal mehr als einen Filedescriptor des Systems verwalten kann. Wenn Sie
zum Beispiel zwei Pipes (eine zum Lesen, eine zum Schreiben) öffnen, enthält
ein einziges IO
-Objekt beide Pipes.]
Hinter einem IO
-Objekt kann mehr stecken, als Sie
denken, aber schlussendlich verwenden Sie es, um in es zu schreiben und von
ihm zu lesen.
In diesem Kapitel konzentrieren wir uns auf die Klasse
IO
und ihre am häufigsten verwendete Unterklasse,
File
. Für nähere Informationen, wie man die
Socket-Klasse für Netzwerkaufgaben verwendet, lesen Sie den Abschnitt, der auf
Seite 473 beginnt.
File.new
erstellen.
aFile = File.new("testfile", "r") # ... Datei verarbeiten aFile.close |
File
-Objekt lesbar, schreibbar oder beides sein
soll (hier haben wir ``testfile
'' mit ``r
'' zum Lesen
geöffnet). Eine vollständige Liste der erlaubten Modi ist auf Seite 331 zu
finden.
Sie können auch optional Berechtigungen angeben, wenn Sie eine Datei
erstellen; für Details lesen Sie die Beschreibung von
File.new
auf Seite 308.
Nach dem Öffnen der Datei können wir mit ihr arbeiten und schreiben und/oder
lesen, wie wir es brauchen. Als verantwortungsvolle Softwarebürger schließen
wir die Datei und versichern uns, dass alle gepufferten Daten geschrieben
wurden und nicht mehr benötigte Resourcen freigemacht worden sind.
Aber hier kann Ihnen Ruby das Leben etwas erleichtern. Auch die Methode
File.open
öffnet eine Datei. Bei normaler Verwendung verhält sie sich wie
File.new
.
Wenn jedoch mit dem Aufruf der Methode ein Block assoziiert ist, verhält sich
open
anders.
Anstatt ein neues File
-Objekt zurückzuliefern, führt
sie den Block aus und übergibt ihm die neu geöffnete Datei als Parameter.
Wenn der Block verlassen wird, wird die Datei automatisch geschlossen.
File.open("testfile", "r") do |aFile| # ... Datei verarbeiten end |
gets
eine Zeile vom
Standard-Input liest, liest aFile.gets
eine Zeile vom Dateiobjekt
aFile
.
I/O-Objekte erfreuen sich jedoch an noch mehr Zugriffsmethoden, alle dazu
gedacht, uns das Leben einfacher zu machen.
IO
-Objekt zu lesen, können Sie auch verschiedene
Iteratoren benutzen.
IO#each_byte
ruft einen Block mit dem nächsten 8-bittigen Byte des
IO
-Objekts auf (in diesem Fall ein Objekt vom Typ
File
).
aFile = File.new("testfile") aFile.each_byte {|ch| putc ch; putc ?. } |
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
ruft den Block mit der nächsten Zeile einer Datei auf.
Im nächsten Beispiel machen wir mit
String#dump
,
die ursprünglichen Newlines sichtbar, damit Sie sehen, dass wir nicht
schummeln.
aFile.each_line {|line| puts "Got #{line.dump}" } |
Got "This is line one\n" Got "This is line two\n" Got "This is line three\n" Got "And so on...\n" |
each_line
jede Zeichensequenz als Zeilentrenner
übergeben. Die Methode wird die Eingabe dementsprechend umbrechen und das
Zeilenende am Ende jeder Datenzeilen zurückgeben. Das ist der Grund, warum Sie
das Zeichen ``\n
'' im Output des vorigen Beispiels sehen.
Im nächsten Beispiel verwenden wir ``e
'' als Zeilentrenner.
aFile.each_line("e") do |line| puts "Got #{ line.dump }" end |
Got "This is line" Got " one" Got "\nThis is line" Got " two\nThis is line" Got " thre" Got "e" Got "\nAnd so on...\n" |
IO.foreach
heraus.
Diese Methode nimmt den Namen einer I/O-Quelle, öffnet diese zum Lesen, ruft
den Iterator für jede Zeile in der Datei auf und schließt die Datei dann
automatisch.
IO.foreach("testfile") { |line| puts line } |
This is line one This is line two This is line three And so on... |
arr = IO.readlines("testfile") |
||
arr.length |
» | 4 |
arr[0] |
» | "This is line one\n" |
puts
und print
aufgerufen, ihnen irgendwelche alten Objekten übergeben und darauf vertraut,
dass Ruby das richtige macht (was es natürlich tut). Aber was genau macht
Ruby?
Die Antwort ist ziemlich einfach. Mit einigen Ausnahmen wird jedes Objekt,
dass Sie puts
und print
übergeben, in einen String
umgewandelt, indem die Methde to_s
des Objekts aufgerufen wird.
Wenn aus irgendeinem Grund to_s
keinen gültigen String
zurückgibt, wird ein String, der den Klassennamen und die ID des Objekts
enthält, erstellt, etwas wie
<ClassName:0x123456>
.
Auch die Ausnahmen sind einfach. Das Objekt nil
wird als der String
``nil'' ausgegeben und ein Array, das puts
übergeben wird, wird
so ausgegeben, als ob jedes Element einzeln puts
übergeben worden
wäre.
Was, wenn Sie binäre Daten schreiben wollen und Ruby nicht damit verwirren
wollen? Nun, normalerweise können Sie einfach
IO#print
benutzen und den String, der die Bytes enhält, die geschrieben werden sollen,
übergeben.
Sie können jedoch auch die low-level Eingabe- und Ausgaberoutinen verwenden,
wenn Sie das wirklich wollen -- schauen Sie sich auf Seite 339 die
Dokumentation zu
IO#sysread
und
IO#syswrite
an.
Und wie bekommt man für die erste Möglichkeit die binären Daten in einen
String? Die beiden gebräuchlichen Wege sind, sie Byte für Byte
hineinzustecken oder
Array#pack
zu verwenden.
str = "" |
» | "" |
str << 1 << 2 << 3 |
» | "\001\002\003" |
|
||
[ 4, 5, 6 ].pack("c*") |
» | "\004\005\006" |
<<
ein Objekt einem Array hinzufügen können, so können Sie
auch ein Objekt an einen Ausgabe-IO
-Stream anhängen:
endl = "\n" $stdout << 99 << " red balloons" << endl |
99 red balloons |
<<
to_s
, um ihre
Argumente in Strings umzuwandeln, bevor sie sie fröhlich auf den Weg schickt.
require 'socket' client = TCPSocket.open('localhost', 'finger') client.send("oracle\n", 0) # 0 bedeutet Standardpaket puts client.readlines client.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, data = h.get('/index.html', nil) if resp.message == "OK" data.scan(/<img src="(.*?)"/) { |x| puts x } end |
images/title_main.gif images/dot.gif images/dot.gif images/dot.gif images/dot.gif images/dot.gif |