class IO
Eine Instanz der Klasse IO (üblicherweise als Stream bezeichnet) repräsentiert einen Ein-/Ausgabe-Stream im zugrunde liegenden Betriebssystem. Klasse IO ist die Grundlage für Eingabe und Ausgabe in Ruby.
Klasse File ist die einzige Klasse im Ruby-Kern, die eine Unterklasse von IO ist. Einige Klassen in der Ruby-Standardbibliothek sind ebenfalls Unterklassen von IO; dazu gehören TCPSocket und UDPSocket.
Die globale Konstante ARGF (auch zugänglich als $<) stellt einen IO-ähnlichen Stream bereit, der den Zugriff auf alle in ARGV gefundenen Dateipfade ermöglicht (oder auf STDIN, wenn ARGV leer ist). ARGF ist selbst keine Unterklasse von IO.
Klasse StringIO stellt einen IO-ähnlichen Stream bereit, der eine String handhabt. StringIO ist selbst keine Unterklasse von IO.
Wichtige Objekte, die auf IO basieren, sind
-
$stdin.
-
$stdout.
-
$stderr.
-
Instanzen der Klasse
File.
Eine Instanz von IO kann mit folgendem erstellt werden
-
IO.new: gibt ein neues IO-Objekt für den gegebenen ganzzahligen Dateideskriptor zurück. -
IO.open: übergibt ein neues IO-Objekt an den gegebenen Block. -
IO.popen: gibt ein neues IO-Objekt zurück, das mit dem $stdin und $stdout eines neu gestarteten Unterprozesses verbunden ist. -
Kernel#open: gibt ein neues IO-Objekt zurück, das mit einer gegebenen Quelle verbunden ist: Stream, Datei oder Unterprozess.
Wie ein File-Stream hat ein IO-Stream
-
Einen Lese-/Schreibmodus, der schreibgeschützt, nur zum Schreiben oder zum Lesen/Schreiben sein kann; siehe Lese-/Schreibmodus.
-
Einen Datenmodus, der nur Text oder Binärdaten sein kann; siehe Datenmodus.
-
Interne und externe Encodings; siehe Encodings.
Und wie andere IO-Streams hat er
-
Eine Position, die bestimmt, wo im Stream die nächste Lese- oder Schreiboperation stattfinden soll; siehe Position.
-
Eine Zeilennummer, die eine spezielle, zeilenorientierte „Position“ ist (anders als die oben genannte Position); siehe Zeilennummer.
Erweiterung io/console
Die Erweiterung io/console bietet zahlreiche Methoden zur Interaktion mit der Konsole; das Einbinden fügt der Klasse IO zahlreiche Methoden hinzu.
Beispiel-Dateien
Viele Beispiele hier verwenden diese Variablen
# English text with newlines. text = <<~EOT First line Second line Fourth line Fifth line EOT # Russian text. russian = "\u{442 435 441 442}" # => "тест" # Binary data. data = "\u9990\u9991\u9992\u9993\u9994" # Text file. File.write('t.txt', text) # File with Russian text. File.write('t.rus', russian) # File with binary data. f = File.new('t.dat', 'wb:UTF-16') f.write(data) f.close
Öffnungsoptionen
Eine Reihe von IO-Methoden akzeptiert optionale Schlüsselwortargumente, die bestimmen, wie ein neuer Stream geöffnet werden soll
-
:mode: Stream-Modus. -
:flags:Integer-Datei-Öffnungsflags; Wennmodeebenfalls angegeben ist, werden die beiden per bitweisem OR verknüpft. -
:external_encoding: Externes Encoding für den Stream. -
:internal_encoding: Internes Encoding für den Stream.'-'ist ein Synonym für das Standard-interne Encoding. Wenn der Wertnilist, erfolgt keine Konvertierung. -
:encoding: Gibt externe und interne Encodings als'extern:intern'an. -
:textmode: Wenn der Wert wahr ist, wird der Modus als reiner Text angegeben, andernfalls als Binärmodus. -
:binmode: Wenn der Wert wahr ist, wird der Modus als Binärmodus angegeben, andernfalls als reiner Textmodus. -
:autoclose: Wenn der Wert wahr ist, wird angegeben, dass derfdgeschlossen wird, wenn der Stream geschlossen wird; andernfalls bleibt er offen. -
:path:Wenn ein String-Wert angegeben ist, wird er ininspectverwendet und ist als Methodepathverfügbar.
Ebenfalls verfügbar sind die Optionen von String#encode, die die Konvertierung zwischen externem und internem Encoding steuern können.
Grundlegende IO
Sie können grundlegende Stream-IO mit diesen Methoden durchführen, die typischerweise auf Multi-Byte-Strings operieren
-
IO#read: Liest und gibt einige oder alle verbleibenden Bytes aus dem Stream zurück. -
IO#write: Schreibt null oder mehr Strings in den Stream; jedes angegebene Objekt, das noch kein String ist, wird überto_skonvertiert.
Position
Ein IO-Stream hat eine nicht-negative ganzzahlige Position, die den Byte-Offset darstellt, an dem die nächste Lese- oder Schreiboperation stattfinden soll. Ein neuer Stream hat die Position Null (und Zeilennummer Null); die Methode rewind setzt die Position (und Zeilennummer) auf Null zurück.
Diese Methoden verwerfen Puffer und die dafür verwendeten Encoding::Converter-Instanzen.
Die relevanten Methoden
-
IO#tell(alias alspos): Gibt die aktuelle Position (in Bytes) im Stream zurück. -
IO#pos=: Setzt die Position des Streams auf die gegebene ganze Zahlnew_position(in Bytes). -
IO#seek: Setzt die Position des Streams auf die gegebene ganze Zahloffset(in Bytes), relativ zu einer gegebenen Positionwhence(die den Anfang, das Ende oder die aktuelle Position angibt). -
IO#rewind: Positioniert den Stream am Anfang (setzt auch die Zeilennummer zurück).
Geöffnete und geschlossene Streams
Ein neuer IO-Stream kann zum Lesen, zum Schreiben oder beides geöffnet sein.
Ein Stream wird automatisch geschlossen, wenn er vom Garbage Collector eingesammelt wird.
Der Versuch, auf einem geschlossenen Stream zu lesen oder zu schreiben, löst eine Ausnahme aus.
Die relevanten Methoden
-
IO#close: Schließt den Stream für Lesen und Schreiben. -
IO#close_read: Schließt den Stream für das Lesen. -
IO#close_write: Schließt den Stream für das Schreiben. -
IO#closed?: Gibt zurück, ob der Stream geschlossen ist.
Dateiende
Sie können abfragen, ob ein Stream an seinem Ende positioniert ist
Sie können zum Dateiende repositionieren, indem Sie die Methode IO#seek verwenden
f = File.new('t.txt') f.eof? # => false f.seek(0, :END) f.eof? # => true f.close
Oder indem Sie den gesamten Stream-Inhalt lesen (was langsamer ist als die Verwendung von IO#seek)
f.rewind f.eof? # => false f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.eof? # => true
Zeilen-IO
Klasse IO unterstützt zeilenorientierte Eingabe und Ausgabe
Zeileneingabe
Klasse IO unterstützt zeilenorientierte Eingabe für Dateien und IO-Streams
Dateizeileneingabe
Sie können Zeilen aus einer Datei mit diesen Methoden lesen
-
IO.foreach: Liest jede Zeile und übergibt sie an den gegebenen Block. -
IO.readlines: Liest und gibt alle Zeilen in einem Array zurück.
Für jede dieser Methoden
-
Sie können Öffnungsoptionen angeben.
-
Die Zeilenanalyse hängt vom effektiven Zeilentrenner ab; siehe Zeilentrenner.
-
Die Länge jeder zurückgegebenen Zeile hängt vom effektiven Zeilenlimit ab; siehe Zeilenlimit.
Stream-Zeileneingabe
Sie können Zeilen aus einem IO-Stream mit diesen Methoden lesen
-
IO#each_line: Liest jede verbleibende Zeile und übergibt sie an den gegebenen Block. -
IO#gets: Gibt die nächste Zeile zurück. -
IO#readline: Wiegets, löst aber am Dateiende eine Ausnahme aus. -
IO#readlines: Gibt alle verbleibenden Zeilen in einem Array zurück.
Für jede dieser Methoden
-
Das Lesen kann mitten in einer Zeile beginnen, abhängig von der Position des Streams; siehe Position.
-
Die Zeilenanalyse hängt vom effektiven Zeilentrenner ab; siehe Zeilentrenner.
-
Die Länge jeder zurückgegebenen Zeile hängt vom effektiven Zeilenlimit ab; siehe Zeilenlimit.
Zeilentrenner
Jede der Zeileneingabemethoden verwendet einen Zeilentrenner: die Zeichenkette, die bestimmt, was als Zeile gilt; sie wird manchmal als Input Record Separator bezeichnet.
Der Standard-Zeilentrenner wird aus der globalen Variablen $/ entnommen, deren Anfangswert "\n" ist.
Im Allgemeinen ist die nächste zu lesende Zeile alle Daten von der aktuellen Position bis zum nächsten Zeilentrenner (aber siehe Spezielle Zeilentrennerwerte).
f = File.new('t.txt') # Method gets with no sep argument returns the next line, according to $/. f.gets # => "First line\n" f.gets # => "Second line\n" f.gets # => "\n" f.gets # => "Fourth line\n" f.gets # => "Fifth line\n" f.close
Sie können einen anderen Zeilentrenner verwenden, indem Sie das Argument sep übergeben
f = File.new('t.txt') f.gets('l') # => "First l" f.gets('li') # => "ine\nSecond li" f.gets('lin') # => "ne\n\nFourth lin" f.gets # => "e\n" f.close
Oder indem Sie die globale Variable $/ setzen
f = File.new('t.txt') $/ = 'l' f.gets # => "First l" f.gets # => "ine\nSecond l" f.gets # => "ine\n\nFourth l" f.close
Spezielle Zeilentrennerwerte
Jede der Zeileneingabemethoden akzeptiert zwei spezielle Werte für den Parameter sep
-
nil: Der gesamte Stream soll gelesen werden („slurped“) und in eine einzelne Zeichenkette gelangen.f = File.new('t.txt') f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.close
-
''(leere Zeichenkette): Der nächste „Absatz“ soll gelesen werden (Absätze werden durch zwei aufeinanderfolgende Zeilentrenner getrennt).f = File.new('t.txt') f.gets('') # => "First line\nSecond line\n\n" f.gets('') # => "Fourth line\nFifth line\n" f.close
Zeilenlimit
Jede der Zeileneingabemethoden verwendet ein ganzzahliges Zeilenlimit, das die Anzahl der zurückgegebenen Bytes begrenzt. (Ein Multi-Byte-Zeichen wird nicht aufgeteilt, und daher kann eine zurückgegebene Zeile etwas länger als das Limit sein).
Der Standardwert für das Limit ist -1; jeder negative Limitwert bedeutet, dass es kein Limit gibt.
Wenn kein Limit vorhanden ist, wird die Zeile nur durch sep bestimmt.
# Text with 1-byte characters. File.open('t.txt') {|f| f.gets(1) } # => "F" File.open('t.txt') {|f| f.gets(2) } # => "Fi" File.open('t.txt') {|f| f.gets(3) } # => "Fir" File.open('t.txt') {|f| f.gets(4) } # => "Firs" # No more than one line. File.open('t.txt') {|f| f.gets(10) } # => "First line" File.open('t.txt') {|f| f.gets(11) } # => "First line\n" File.open('t.txt') {|f| f.gets(12) } # => "First line\n" # Text with 2-byte characters, which will not be split. File.open('t.rus') {|f| f.gets(1).size } # => 1 File.open('t.rus') {|f| f.gets(2).size } # => 1 File.open('t.rus') {|f| f.gets(3).size } # => 2 File.open('t.rus') {|f| f.gets(4).size } # => 2
Zeilentrenner und Zeilenlimit
Mit den Argumenten sep und limit kombiniert dies die beiden Verhaltensweisen
-
Gibt die nächste Zeile zurück, wie durch den Zeilentrenner
sepbestimmt. -
Aber gibt nicht mehr Bytes zurück, als das Limit
limiterlaubt.
Beispiel
File.open('t.txt') {|f| f.gets('li', 20) } # => "First li" File.open('t.txt') {|f| f.gets('li', 2) } # => "Fi"
Zeilennummer
Ein lesbarer IO-Stream hat eine nicht-negative ganzzahlige Zeilennummer
-
IO#lineno: Gibt die Zeilennummer zurück. -
IO#lineno=: Setzt und gibt die Zeilennummer zurück.
Sofern nicht durch einen Aufruf der Methode IO#lineno= geändert, ist die Zeilennummer die Anzahl der Zeilen, die von bestimmten zeilenorientierten Methoden gelesen wurden, gemäß dem effektiven Zeilentrenner
-
IO.foreach: Erhöht die Zeilennummer bei jedem Aufruf des Blocks. -
IO#each_line: Erhöht die Zeilennummer bei jedem Aufruf des Blocks. -
IO#gets: Erhöht die Zeilennummer. -
IO#readline: Erhöht die Zeilennummer. -
IO#readlines: Erhöht die Zeilennummer für jede gelesene Zeile.
Ein neuer Stream hat zunächst die Zeilennummer Null (und Position Null); die Methode rewind setzt die Zeilennummer (und Position) auf Null zurück.
f = File.new('t.txt') f.lineno # => 0 f.gets # => "First line\n" f.lineno # => 1 f.rewind f.lineno # => 0 f.close
Das Lesen von Zeilen aus einem Stream ändert normalerweise seine Zeilennummer.
f = File.new('t.txt', 'r') f.lineno # => 0 f.readline # => "This is line one.\n" f.lineno # => 1 f.readline # => "This is the second line.\n" f.lineno # => 2 f.readline # => "Here's the third line.\n" f.lineno # => 3 f.eof? # => true f.close
Das Iterieren über Zeilen in einem Stream ändert normalerweise seine Zeilennummer.
File.open('t.txt') do |f| f.each_line do |line| p "position=#{f.pos} eof?=#{f.eof?} lineno=#{f.lineno}" end end
Ausgabe
"position=11 eof?=false lineno=1" "position=23 eof?=false lineno=2" "position=24 eof?=false lineno=3" "position=36 eof?=false lineno=4" "position=47 eof?=true lineno=5"
Im Gegensatz zur Position des Streams beeinflusst die Zeilennummer nicht, wo die nächste Lese- oder Schreiboperation stattfindet.
f = File.new('t.txt') f.lineno = 1000 f.lineno # => 1000 f.gets # => "First line\n" f.lineno # => 1001 f.close
Mit der Zeilennummer verbunden ist die globale Variable $.
-
Wenn ein Stream geöffnet wird, wird
$.nicht gesetzt; sein Wert bleibt von früheren Aktivitäten im Prozess übrig.$. = 41 f = File.new('t.txt') $. = 41 # => 41 f.close
-
Wenn ein Stream gelesen wird, wird
$.auf die Zeilennummer für diesen Stream gesetzt.f0 = File.new('t.txt') f1 = File.new('t.dat') f0.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"] $. # => 5 f1.readlines # => ["\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94"] $. # => 1 f0.close f1.close
-
Die Methoden
IO#rewindundIO#seekbeeinflussen$.nicht.f = File.new('t.txt') f.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"] $. # => 5 f.rewind f.seek(0, :SET) $. # => 5 f.close
Zeilenausgabe
Sie können zeilenweise in einen IO-Stream mit dieser Methode schreiben
-
IO#puts: Schreibt Objekte in den Stream.
Zeichen-IO
Sie können einen IO-Stream Zeichen für Zeichen mit diesen Methoden verarbeiten
-
IO#getc: Liest und gibt das nächste Zeichen aus dem Stream zurück. -
IO#readchar: Wiegetc, löst aber am Dateiende eine Ausnahme aus. -
IO#ungetc: Schiebt ein Zeichen oder eine Ganzzahl zurück („unsheftet“) in den Stream. -
IO#putc: Schreibt ein Zeichen in den Stream. -
IO#each_char: Liest jedes verbleibende Zeichen im Stream und übergibt das Zeichen an den gegebenen Block.
Byte-IO
Sie können einen IO-Stream Byte für Byte mit diesen Methoden verarbeiten
-
IO#getbyte: Gibt das nächste 8-Bit-Byte als Ganzzahl im Bereich 0..255 zurück. -
IO#readbyte: Wiegetbyte, löst aber am Dateiende eine Ausnahme aus. -
IO#ungetbyte: Schiebt ein Byte zurück („unsheftet“) in den Stream. -
IO#each_byte: Liest jedes verbleibende Byte im Stream und übergibt das Byte an den gegebenen Block.
Codepoint-IO
Sie können einen IO-Stream Codepoint für Codepoint verarbeiten
-
IO#each_codepoint: Liest jeden verbleibenden Codepoint und übergibt ihn an den gegebenen Block.
Was gibt es hier
Zuerst, was anderswo ist. Klasse IO
-
Erbt von Klasse Object.
-
Beinhaltet das Modul Enumerable, das Dutzende zusätzlicher Methoden bereitstellt.
Hier bietet die Klasse IO Methoden, die nützlich sind für
Erstellen
-
::new(alias als::for_fd): Erstellt und gibt ein neues IO-Objekt für den gegebenen ganzzahligen Dateideskriptor zurück. -
::open: Erstellt ein neues IO-Objekt. -
::pipe: Erstellt ein verbundenes Paar von Lese- und Schreib-IO-Objekten. -
::popen: Erstellt ein IO-Objekt zur Interaktion mit einem Unterprozess. -
::select: Wählt aus, welche gegebenen IO-Instanzen bereit zum Lesen, Schreiben sind oder ausstehende Ausnahmen haben.
Lesen
-
::binread: Gibt einen Binärstring mit allen oder einem Teil der Bytes aus der gegebenen Datei zurück. -
::read: Gibt einen String mit allen oder einem Teil der Bytes aus der gegebenen Datei zurück. -
::readlines: Gibt ein Array von Strings zurück, die die Zeilen aus der gegebenen Datei sind. -
getbyte: Gibt das nächste 8-Bit-Byte, das ausselfgelesen wurde, als Ganzzahl zurück. -
getc: Gibt das nächste Zeichen, das ausselfgelesen wurde, als String zurück. -
gets: Gibt die Zeile zurück, die ausselfgelesen wurde. -
pread: Gibt alle oder die nächsten n Bytes zurück, die ausselfgelesen wurden, ohne den Offset des Empfängers zu aktualisieren. -
read: Gibt alle verbleibenden oder die nächsten n Bytes zurück, die ausselffür ein gegebenes n gelesen wurden. -
read_nonblock: die nächsten n Bytes, die ausselffür ein gegebenes n gelesen wurden, im Nicht-Blockierungsmodus. -
readbyte: Gibt das nächste ausselfgelesene Byte zurück; dasselbe wiegetbyte, löst aber am Dateiende eine Ausnahme aus. -
readchar: Gibt das nächste ausselfgelesene Zeichen zurück; dasselbe wiegetc, löst aber am Dateiende eine Ausnahme aus. -
readline: Gibt die nächste ausselfgelesene Zeile zurück; dasselbe wie getline, löst aber am Dateiende eine Ausnahme aus. -
readlines: Gibt ein Array aller ausselfgelesenen Zeilen zurück. -
readpartial: Gibt bis zur gegebenen Anzahl von Bytes ausselfzurück.
Schreiben
-
::binwrite: Schreibt den gegebenen String in die Datei am gegebenen Pfad, im Binärmodus. -
::write: Schreibt den gegebenen String inself. -
<<: Hängt den gegebenen String anselfan. -
print: Gibt die zuletzt gelesene Zeile oder die gegebenen Objekte inselfaus. -
printf: Schreibt inselfbasierend auf der gegebenen Formatzeichenkette und den Objekten. -
putc: Schreibt ein Zeichen inself. -
puts: Schreibt Zeilen inselfund stellt sicher, dass jede Zeile mit einem Zeilenumbruch endet. -
pwrite: Schreibt den gegebenen String am gegebenen Offset, ohne den Offset des Empfängers zu aktualisieren. -
write: Schreibt einen oder mehrere gegebene Strings inself. -
write_nonblock: Schreibt einen oder mehrere gegebene Strings inselfim Nicht-Blockierungsmodus.
Positionieren
-
lineno: Gibt die aktuelle Zeilennummer inselfzurück. -
lineno=: Setzt die Zeilennummer inself. -
pos(alias alstell): Gibt den aktuellen Byte-Offset inselfzurück. -
pos=: Setzt den Byte-Offset inself. -
reopen: Ordnetselfneu einem neuen oder bestehenden IO-Stream zu. -
rewind: Positioniertselfam Anfang der Eingabe. -
seek: Setzt den Offset fürselfrelativ zur gegebenen Position.
Iterieren
-
::foreach: Übergibt jede Zeile der gegebenen Datei an den Block. -
each(alias alseach_line): Ruft den gegebenen Block mit jeder aufeinanderfolgenden Zeile inselfauf. -
each_byte: Ruft den gegebenen Block mit jedem aufeinanderfolgenden Byte inselfals Ganzzahl auf. -
each_char: Ruft den gegebenen Block mit jedem aufeinanderfolgenden Zeichen inselfals String auf. -
each_codepoint: Ruft den gegebenen Block mit jedem aufeinanderfolgenden Codepoint inselfals Ganzzahl auf.
Einstellungen
-
autoclose=: Setzt, obselfautomatisch geschlossen wird. -
binmode: Setztselfin den Binärmodus. -
close: Schließtself. -
close_on_exec=: Setzt das Close-on-exec-Flag. -
close_read: Schließtselffür das Lesen. -
close_write: Schließtselffür das Schreiben. -
set_encoding: Setzt das Encoding fürself. -
set_encoding_by_bom: Setzt das Encoding fürselfbasierend auf seinem Unicode Byte Order Mark. -
sync=: Setzt den Sync-Modus auf den gegebenen Wert.
Abfragen
-
autoclose?: Gibt zurück, obselfautomatisch geschlossen wird. -
binmode?: Gibt zurück, obselfim Binärmodus ist. -
close_on_exec?: Gibt das Close-on-exec-Flag fürselfzurück. -
closed?: Gibt zurück, obselfgeschlossen ist. -
eof?(alias alseof): Gibt zurück, obselfam Dateiende ist. -
external_encoding: Gibt das externe Encoding-Objekt fürselfzurück. -
fileno(alias alsto_i): Gibt den ganzzahligen Dateideskriptor fürselfzurück. -
internal_encoding: Gibt das interne Encoding-Objekt fürselfzurück. -
pid: Gibt die Prozess-ID eines Kindprozesses zurück, der mitselfverbunden ist, wennselfdurch::popenerstellt wurde. -
stat: Gibt dasFile::Stat-Objekt zurück, das Statusinformationen fürselfenthält. -
sync: Gibt zurück, obselfim Sync-Modus ist. -
tty?(alias alsisatty): Gibt zurück, obselfein Terminal ist.
Buffering
-
fdatasync: Schreibt sofort alle gepufferten Daten inselfauf die Festplatte. -
flush: Spült alle gepufferten Daten inselfzum zugrunde liegenden Betriebssystem. -
fsync: Schreibt sofort alle gepufferten Daten und Attribute inselfauf die Festplatte. -
ungetbyte: Stellt dem Puffer fürselfdie gegebene ganzzahlige Byte oder Zeichenkette voran. -
ungetc: Stellt dem Puffer fürselfdie gegebene Zeichenkette voran.
Low-Level-Zugriff
-
::sysopen: Öffnet die Datei, die durch ihren Pfad gegeben ist, und gibt den ganzzahligen Dateideskriptor zurück. -
advise: Kündigt die Absicht an, auf Daten vonselfauf eine bestimmte Weise zuzugreifen. -
fcntl: Leitet einen Low-Level-Befehl an die Datei weiter, die durch den gegebenen Dateideskriptor spezifiziert ist. -
ioctl: Leitet einen Low-Level-Befehl an das Gerät weiter, das durch den gegebenen Dateideskriptor spezifiziert ist. -
sysread: Gibt bis zu den nächsten n Bytes zurück, die mit einem Low-Level-Read aus self gelesen wurden. -
sysseek: Setzt den Offset fürself. -
syswrite: Schreibt den gegebenen String mit einem Low-Level-Write inself.
Sonstiges
-
::copy_stream: Kopiert Daten von einer Quelle zu einem Ziel, wobei beides Dateipfade oder IO-ähnliche Objekte sein können. -
::try_convert: Gibt ein neues IO-Objekt zurück, das aus der Konvertierung des gegebenen Objekts resultiert. -
inspect: Gibt die String-Repräsentation vonselfzurück.
Constants
- EWOULDBLOCKWaitReadable
-
gleich wie
IO::EAGAINWaitReadable - EWOULDBLOCKWaitWritable
-
gleich wie
IO::EAGAINWaitWritable - PRIORITY
-
Prioritätsereignismaske für
IO#wait. - READABLE
-
Lesbares Ereignismaske für
IO#wait. - SEEK_CUR
-
Setzt die I/O-Position von der aktuellen Position
- SEEK_DATA
-
Setzt die I/O-Position auf den nächsten Ort, der Daten enthält
- SEEK_END
-
Setzt die I/O-Position vom Ende aus
- SEEK_HOLE
-
Setzt die I/O-Position auf das nächste Loch
- SEEK_SET
-
Setzt die I/O-Position vom Anfang aus
- WRITABLE
-
Schreibbares Ereignismaske für
IO#wait.
Öffentliche Klassenmethoden
Source
static VALUE
rb_io_s_binread(int argc, VALUE *argv, VALUE io)
{
VALUE offset;
struct foreach_arg arg;
enum rb_io_mode fmode = FMODE_READABLE|FMODE_BINMODE;
enum {
oflags = O_RDONLY
#ifdef O_BINARY
|O_BINARY
#endif
};
struct rb_io_encoding convconfig = {NULL, NULL, 0, Qnil};
rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
FilePathValue(argv[0]);
convconfig.enc = rb_ascii8bit_encoding();
arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
if (NIL_P(arg.io)) return Qnil;
arg.argv = argv+1;
arg.argc = (argc > 1) ? 1 : 0;
if (!NIL_P(offset)) {
struct seek_arg sarg;
int state = 0;
sarg.io = arg.io;
sarg.offset = offset;
sarg.mode = SEEK_SET;
rb_protect(seek_before_access, (VALUE)&sarg, &state);
if (state) {
rb_io_close(arg.io);
rb_jump_tag(state);
}
}
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
Verhält sich wie IO.read, außer dass der Stream im Binärmodus mit ASCII-8BIT-Encoding geöffnet wird.
Wenn diese Methode von der Klasse IO (aber nicht von Unterklassen von IO) aufgerufen wird, birgt sie potenzielle Sicherheitslücken, wenn sie mit nicht vertrauenswürdigen Eingaben aufgerufen wird; siehe Command Injection.
Source
static VALUE
rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
{
return io_s_write(argc, argv, io, 1);
}
Verhält sich wie IO.write, außer dass der Stream im Binärmodus mit ASCII-8BIT-Encoding geöffnet wird.
Wenn diese Methode von der Klasse IO (aber nicht von Unterklassen von IO) aufgerufen wird, birgt sie potenzielle Sicherheitslücken, wenn sie mit nicht vertrauenswürdigen Eingaben aufgerufen wird; siehe Command Injection.
Source
static VALUE
console_dev(int argc, VALUE *argv, VALUE klass)
{
VALUE con = 0;
VALUE sym = 0;
if (argc) {
Check_Type(sym = argv[0], T_SYMBOL);
}
// Force the class to be File.
if (klass == rb_cIO) klass = rb_cFile;
if (console_dev_get(klass, &con)) {
if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) {
console_dev_remove(klass);
con = 0;
}
}
if (sym) {
if (sym == ID2SYM(id_close) && argc == 1) {
if (con) {
rb_io_close(con);
console_dev_remove(klass);
con = 0;
}
return Qnil;
}
}
if (!con) {
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
# define CONSOLE_DEVICE "/dev/tty"
#elif defined _WIN32
# define CONSOLE_DEVICE "con$"
# define CONSOLE_DEVICE_FOR_READING "conin$"
# define CONSOLE_DEVICE_FOR_WRITING "conout$"
#endif
#ifndef CONSOLE_DEVICE_FOR_READING
# define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
#endif
#ifdef CONSOLE_DEVICE_FOR_WRITING
VALUE out;
#endif
int fd;
VALUE path = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
#ifdef CONSOLE_DEVICE_FOR_WRITING
fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0);
if (fd < 0) return Qnil;
out = rb_io_open_descriptor(klass, fd, FMODE_WRITABLE | FMODE_SYNC, path, Qnil, NULL);
#endif
fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_READING, O_RDWR, 0);
if (fd < 0) {
#ifdef CONSOLE_DEVICE_FOR_WRITING
rb_io_close(out);
#endif
return Qnil;
}
con = rb_io_open_descriptor(klass, fd, FMODE_READWRITE | FMODE_SYNC, path, Qnil, NULL);
#ifdef CONSOLE_DEVICE_FOR_WRITING
rb_io_set_write_io(con, out);
#endif
console_dev_set(klass, con);
}
if (sym) {
return rb_f_send(argc, argv, con);
}
return con;
}
Source
static VALUE
rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
{
VALUE src, dst, length, src_offset;
struct copy_stream_struct st;
MEMZERO(&st, struct copy_stream_struct, 1);
rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
st.src = src;
st.dst = dst;
st.src_fptr = NULL;
st.dst_fptr = NULL;
if (NIL_P(length))
st.copy_length = (rb_off_t)-1;
else
st.copy_length = NUM2OFFT(length);
if (NIL_P(src_offset))
st.src_offset = (rb_off_t)-1;
else
st.src_offset = NUM2OFFT(src_offset);
rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
return OFFT2NUM(st.total);
}
Kopiert von der gegebenen src zur gegebenen dst und gibt die Anzahl der kopierten Bytes zurück.
-
Die gegebene
srcmuss eines der folgenden sein-
Der Pfad zu einer lesbaren Datei, aus der Quelldaten gelesen werden sollen.
-
Ein IO-ähnliches Objekt, das zum Lesen geöffnet und in der Lage ist, auf die Methode
:readpartialoder:readzu reagieren.
-
-
Die gegebene
dstmuss eines der folgenden sein-
Der Pfad zu einer schreibbaren Datei, in die Daten geschrieben werden sollen.
-
Ein IO-ähnliches Objekt, das zum Schreiben geöffnet und in der Lage ist, auf die Methode
:writezu reagieren.
-
Die Beispiele hier verwenden die Datei t.txt als Quelle
File.read('t.txt') # => "First line\nSecond line\n\nThird line\nFourth line\n" File.read('t.txt').size # => 47
Wenn nur die Argumente src und dst gegeben sind, wird der gesamte Quellstream kopiert.
# Paths. IO.copy_stream('t.txt', 't.tmp') # => 47 # IOs (recall that a File is also an IO). src_io = File.open('t.txt', 'r') # => #<File:t.txt> dst_io = File.open('t.tmp', 'w') # => #<File:t.tmp> IO.copy_stream(src_io, dst_io) # => 47 src_io.close dst_io.close
Mit dem Argument src_length, einer nicht-negativen Ganzzahl, werden nicht mehr als so viele Bytes kopiert.
IO.copy_stream('t.txt', 't.tmp', 10) # => 10 File.read('t.tmp') # => "First line"
Mit dem ebenfalls gegebenen Argument src_offset wird der Quellstream ab diesem Offset gelesen.
IO.copy_stream('t.txt', 't.tmp', 11, 11) # => 11 IO.read('t.tmp') # => "Second line"
Source
static VALUE
rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
{
VALUE io = rb_obj_alloc(klass);
rb_io_initialize(argc, argv, io);
return io;
}
Synonym für IO.new.
Source
static VALUE
rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
{
VALUE opt;
int orig_argc = argc;
struct foreach_arg arg;
struct getline_arg garg;
argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
RETURN_ENUMERATOR(self, orig_argc, argv);
extract_getline_args(argc-1, argv+1, &garg);
open_key_args(self, argc, argv, opt, &arg);
if (NIL_P(arg.io)) return Qnil;
extract_getline_opts(opt, &garg);
check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
}
Ruft den Block mit jeder aufeinanderfolgenden Zeile auf, die aus dem Stream gelesen wird.
Wenn diese Methode von der Klasse IO (aber nicht von Unterklassen von IO) aufgerufen wird, birgt sie potenzielle Sicherheitslücken, wenn sie mit nicht vertrauenswürdigen Eingaben aufgerufen wird; siehe Command Injection.
Das erste Argument muss ein String sein, der der Pfad zu einer Datei ist.
Wenn nur das Argument path gegeben ist, werden Zeilen aus der Datei unter dem gegebenen path geparst, wie durch den Standard-Zeilentrenner bestimmt, und der Block wird mit jeder aufeinanderfolgenden Zeile aufgerufen.
File.foreach('t.txt') {|line| p line }
Ausgabe: dieselbe wie oben.
Für beide Formen, Befehl und Pfad, sind die verbleibenden Argumente dieselben.
Wenn das Argument sep gegeben ist, werden Zeilen wie durch diesen Zeilentrenner bestimmt geparst (siehe Zeilentrenner).
File.foreach('t.txt', 'li') {|line| p line }
Ausgabe
"First li" "ne\nSecond li" "ne\n\nThird li" "ne\nFourth li" "ne\n"
Jeder Absatz
File.foreach('t.txt', '') {|paragraph| p paragraph }
Ausgabe
"First line\nSecond line\n\n" "Third line\nFourth line\n"
Wenn das Argument limit gegeben ist, werden Zeilen wie durch den Standard-Zeilentrenner und das gegebene Zeilenlängenlimit bestimmt geparst (siehe Zeilentrenner und Zeilenlimit).
File.foreach('t.txt', 7) {|line| p line }
Ausgabe
"First l" "ine\n" "Second " "line\n" "\n" "Third l" "ine\n" "Fourth l" "line\n"
Mit den Argumenten sep und limit werden die beiden Verhaltensweisen kombiniert (siehe Zeilentrenner und Zeilenlimit).
Optionale Schlüsselwortargumente opts spezifizieren
Gibt einen Enumerator zurück, wenn kein Block gegeben ist.
Source
static VALUE
rb_io_initialize(int argc, VALUE *argv, VALUE io)
{
VALUE fnum, vmode;
VALUE opt;
rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
return io_initialize(io, fnum, vmode, opt);
}
Erstellt und gibt ein neues IO-Objekt (Dateistream) aus einem Dateideskriptor zurück.
IO.new kann für die Interaktion mit Low-Level-Bibliotheken nützlich sein. Für höherwertige Interaktionen ist es möglicherweise einfacher, den Dateistream mit File.open zu erstellen.
Das Argument fd muss ein gültiger Dateideskriptor (Integer) sein.
path = 't.tmp' fd = IO.sysopen(path) # => 3 IO.new(fd) # => #<IO:fd 3>
Das neue IO-Objekt erbt keine Kodierung (da der ganzzahlige Dateideskriptor keine Kodierung hat).
fd = IO.sysopen('t.rus', 'rb') io = IO.new(fd) io.external_encoding # => #<Encoding:UTF-8> # Not ASCII-8BIT.
Das optionale Argument mode (Standard ist ‚r‘) muss einen gültigen Modus angeben; siehe Zugriffsmodi.
IO.new(fd, 'w') # => #<IO:fd 3> IO.new(fd, File::WRONLY) # => #<IO:fd 3>
Optionale Schlüsselwortargumente opts spezifizieren
Beispiele
IO.new(fd, internal_encoding: nil) # => #<IO:fd 3> IO.new(fd, autoclose: true) # => #<IO:fd 3>
Source
static VALUE
rb_io_s_open(int argc, VALUE *argv, VALUE klass)
{
VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, io, io_close, io);
}
return io;
}
Erstellt ein neues IO-Objekt über IO.new mit den angegebenen Argumenten.
Wenn kein Block gegeben ist, wird das IO-Objekt zurückgegeben.
Wenn ein Block gegeben ist, wird der Block mit dem IO-Objekt aufgerufen und der Wert des Blocks zurückgegeben.
Source
static VALUE
rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
{
int pipes[2], state;
VALUE r, w, args[3], v1, v2;
VALUE opt;
rb_io_t *fptr, *fptr2;
struct io_encoding_set_args ies_args;
enum rb_io_mode fmode = 0;
VALUE ret;
argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
if (rb_pipe(pipes) < 0)
rb_sys_fail(0);
args[0] = klass;
args[1] = INT2NUM(pipes[0]);
args[2] = INT2FIX(O_RDONLY);
r = rb_protect(io_new_instance, (VALUE)args, &state);
if (state) {
close(pipes[0]);
close(pipes[1]);
rb_jump_tag(state);
}
GetOpenFile(r, fptr);
ies_args.fptr = fptr;
ies_args.v1 = v1;
ies_args.v2 = v2;
ies_args.opt = opt;
rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
if (state) {
close(pipes[1]);
io_close(r);
rb_jump_tag(state);
}
args[1] = INT2NUM(pipes[1]);
args[2] = INT2FIX(O_WRONLY);
w = rb_protect(io_new_instance, (VALUE)args, &state);
if (state) {
close(pipes[1]);
if (!NIL_P(r)) rb_io_close(r);
rb_jump_tag(state);
}
GetOpenFile(w, fptr2);
rb_io_synchronized(fptr2);
extract_binmode(opt, &fmode);
if ((fmode & FMODE_BINMODE) && NIL_P(v1)) {
rb_io_ascii8bit_binmode(r);
rb_io_ascii8bit_binmode(w);
}
#if DEFAULT_TEXTMODE
if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
fptr->mode &= ~FMODE_TEXTMODE;
setmode(fptr->fd, O_BINARY);
}
#if RUBY_CRLF_ENVIRONMENT
if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
}
#endif
#endif
fptr->mode |= fmode;
#if DEFAULT_TEXTMODE
if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
fptr2->mode &= ~FMODE_TEXTMODE;
setmode(fptr2->fd, O_BINARY);
}
#endif
fptr2->mode |= fmode;
ret = rb_assoc_new(r, w);
if (rb_block_given_p()) {
VALUE rw[2];
rw[0] = r;
rw[1] = w;
return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
}
return ret;
}
Erstellt ein Paar von Pipe-Endpunkten, read_io und write_io, die miteinander verbunden sind.
Wenn das Argument enc_string gegeben ist, muss es ein String sein, der eine der folgenden enthält:
-
Den Namen der Kodierung, die als externe Kodierung verwendet werden soll.
-
Die durch Doppelpunkte getrennten Namen zweier Kodierungen, die als externe und interne Kodierung verwendet werden sollen.
Wenn das Argument int_enc gegeben ist, muss es ein Encoding-Objekt oder ein Kodierungsnamensstring sein, der die zu verwendende interne Kodierung angibt; wenn das Argument ext_enc ebenfalls gegeben ist, muss es ein Encoding-Objekt oder ein Kodierungsnamensstring sein, der die zu verwendende externe Kodierung angibt.
Der von read_io gelesene String wird mit der externen Kodierung getaggt; wenn auch eine interne Kodierung angegeben ist, wird der String in diese Kodierung konvertiert und mit dieser getaggt.
Wenn eine Kodierung angegeben ist, geben optionale Hash-Argumente die Konvertierungsoption an.
Optionale Schlüsselwortargumente opts spezifizieren
Wenn kein Block gegeben ist, werden die beiden Endpunkte in einem Array zurückgegeben.
IO.pipe # => [#<IO:fd 4>, #<IO:fd 5>]
Wenn ein Block gegeben ist, wird der Block mit den beiden Endpunkten aufgerufen; beide Endpunkte werden geschlossen und der Wert des Blocks zurückgegeben.
IO.pipe {|read_io, write_io| p read_io; p write_io }
Ausgabe
#<IO:fd 6> #<IO:fd 7>
Nicht auf allen Plattformen verfügbar.
Im folgenden Beispiel schließen die beiden Prozesse die Enden der Pipe, die sie nicht verwenden. Dies ist nicht nur eine kosmetische Nettigkeit. Das Leseende einer Pipe erzeugt keine End-of-File-Bedingung, wenn noch Schreiber die Pipe offen haben. Im Fall des Elternprozesses wird rd.read niemals zurückkehren, wenn es nicht zuerst ein wr.close aufruft.
rd, wr = IO.pipe if fork wr.close puts "Parent got: <#{rd.read}>" rd.close Process.wait else rd.close puts 'Sending message to parent' wr.write "Hi Dad" wr.close end
ergibt
Sending message to parent Parent got: <Hi Dad>
Source
static VALUE
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
{
VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil;
if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
switch (argc) {
case 2:
pmode = argv[1];
case 1:
pname = argv[0];
break;
default:
{
int ex = !NIL_P(opt);
rb_error_arity(argc + ex, 1 + ex, 2 + ex);
}
}
return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
}
Führt den Befehl cmd als Unterprozess aus, dessen $stdin und $stdout mit einem neuen Stream io verbunden sind.
Diese Methode hat potenzielle Sicherheitslücken, wenn sie mit nicht vertrauenswürdigen Eingaben aufgerufen wird. Siehe Command Injection.
Wenn kein Block gegeben ist, wird der neue Stream zurückgegeben, der je nach angegebenem mode zum Lesen, Schreiben oder beides geöffnet sein kann. Der Stream sollte explizit (schließlich) geschlossen werden, um Ressourcenlecks zu vermeiden.
Wenn ein Block gegeben ist, wird der Stream an den Block übergeben (wiederum zum Lesen, Schreiben oder beides geöffnet); wenn der Block beendet wird, wird der Stream geschlossen, der Wert des Blocks zurückgegeben und die globale Variable $? auf den Exit-Status des Kindes gesetzt.
Das optionale Argument mode kann jeder gültige IO-Modus sein. Siehe Zugriffsmodi.
Das erforderliche Argument cmd bestimmt, welches der folgenden Ereignisse eintritt
-
Der Prozess wird geforkt.
-
Ein bestimmtes Programm wird in einer Shell ausgeführt.
-
Ein bestimmtes Programm wird mit angegebenen Argumenten ausgeführt.
-
Ein bestimmtes Programm wird mit angegebenen Argumenten und einem angegebenen
argv0ausgeführt.
Jede dieser Optionen wird unten detailliert beschrieben.
Das optionale Hash-Argument env gibt Namens-/Wertpaare an, die zu den Umgebungsvariablen für den Unterprozess hinzugefügt werden sollen.
IO.popen({'FOO' => 'bar'}, 'ruby', 'r+') do |pipe| pipe.puts 'puts ENV["FOO"]' pipe.close_write pipe.gets end => "bar\n"
Optionale Schlüsselwortargumente opts spezifizieren
-
Optionen für
Kernel#spawn.
Geforkter Prozess
Wenn das Argument cmd der 1-Zeichen-String '-' ist, wird der Prozess geforkt.
IO.popen('-') do |pipe| if pipe $stderr.puts "In parent, child pid is #{pipe.pid}\n" else $stderr.puts "In child, pid is #{$$}\n" end end
Ausgabe
In parent, child pid is 26253 In child, pid is 26253
Beachten Sie, dass dies nicht auf allen Plattformen unterstützt wird.
Shell-Unterprozess
Wenn das Argument cmd ein einzelner String ist (aber nicht '-'), wird das Programm namens cmd als Shell-Befehl ausgeführt.
IO.popen('uname') do |pipe| pipe.readlines end
Ausgabe
["Linux\n"]
Ein weiteres Beispiel
IO.popen('/bin/sh', 'r+') do |pipe| pipe.puts('ls') pipe.close_write $stderr.puts pipe.readlines.size end
Ausgabe
213
Programm-Unterprozess
Wenn das Argument cmd ein Array von Strings ist, wird das Programm namens cmd[0] mit allen Elementen von cmd als Argumenten ausgeführt.
IO.popen(['du', '..', '.']) do |pipe| $stderr.puts pipe.readlines.size end
Ausgabe
1111
Programm-Unterprozess mit argv0
Wenn das Argument cmd ein Array ist, dessen erstes Element ein 2-Element-String-Array ist und dessen übrige Elemente (falls vorhanden) Strings sind.
-
cmd[0][0](der erste String im verschachtelten Array) ist der Name eines Programms, das ausgeführt wird. -
cmd[0][1](der zweite String im verschachtelten Array) wird alsargv[0]des Programms gesetzt. -
cmd[1..-1](die Strings im äußeren Array) sind die Argumente des Programms.
Beispiel (setzt $0 auf ‚foo‘)
IO.popen([['/bin/sh', 'foo'], '-c', 'echo $0']).read # => "foo\n"
Einige spezielle Beispiele
# Set IO encoding. IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io| euc_jp_string = nkf_io.read } # Merge standard output and standard error using Kernel#spawn option. See Kernel#spawn. IO.popen(["ls", "/", :err=>[:child, :out]]) do |io| ls_result_with_error = io.read end # Use mixture of spawn options and IO options. IO.popen(["ls", "/"], :err=>[:child, :out]) do |io| ls_result_with_error = io.read end f = IO.popen("uname") p f.readlines f.close puts "Parent is #{Process.pid}" IO.popen("date") {|f| puts f.gets } IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"} p $? IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f| f.puts "bar"; f.close_write; puts f.gets }
Ausgabe (aus dem letzten Abschnitt)
["Linux\n"] Parent is 21346 Thu Jan 15 22:41:19 JST 2009 21346 is here, f is #<IO:fd 3> 21352 is here, f is nil #<Process::Status: pid 21352 exit 0> <foo>bar;zot;
Wirft Ausnahmen, die von IO.pipe und Kernel.spawn geworfen werden.
Source
static VALUE
rb_io_s_read(int argc, VALUE *argv, VALUE io)
{
VALUE opt, offset;
long off;
struct foreach_arg arg;
argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
if (!NIL_P(offset) && (off = NUM2LONG(offset)) < 0) {
rb_raise(rb_eArgError, "negative offset %ld given", off);
}
open_key_args(io, argc, argv, opt, &arg);
if (NIL_P(arg.io)) return Qnil;
if (!NIL_P(offset)) {
struct seek_arg sarg;
int state = 0;
sarg.io = arg.io;
sarg.offset = offset;
sarg.mode = SEEK_SET;
rb_protect(seek_before_access, (VALUE)&sarg, &state);
if (state) {
rb_io_close(arg.io);
rb_jump_tag(state);
}
if (arg.argc == 2) arg.argc = 1;
}
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
Öffnet den Stream, liest und gibt einen Teil oder den gesamten Inhalt zurück und schließt den Stream; gibt nil zurück, wenn keine Bytes gelesen wurden.
Wenn diese Methode von der Klasse IO (aber nicht von Unterklassen von IO) aufgerufen wird, birgt sie potenzielle Sicherheitslücken, wenn sie mit nicht vertrauenswürdigen Eingaben aufgerufen wird; siehe Command Injection.
Das erste Argument muss ein String sein, der der Pfad zu einer Datei ist.
Wenn nur das Argument path gegeben ist, wird im Textmodus gelesen und der gesamte Inhalt der Datei am angegebenen Pfad zurückgegeben.
IO.read('t.txt') # => "First line\nSecond line\n\nThird line\nFourth line\n"
Unter Windows kann der Textmodus das Lesen beenden und Bytes in der Datei ungelesen lassen, wenn bestimmte Sonderbytes auftreten. Erwägen Sie die Verwendung von IO.binread, wenn alle Bytes in der Datei gelesen werden sollen.
Mit dem Argument length werden length Bytes zurückgegeben, falls verfügbar.
IO.read('t.txt', 7) # => "First l" IO.read('t.txt', 700) # => "First line\r\nSecond line\r\n\r\nFourth line\r\nFifth line\r\n"
Mit den Argumenten length und offset werden length Bytes zurückgegeben, falls verfügbar, beginnend beim angegebenen offset.
IO.read('t.txt', 10, 2) # => "rst line\nS" IO.read('t.txt', 10, 200) # => nil
Optionale Schlüsselwortargumente opts spezifizieren
Source
static VALUE
rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
{
VALUE opt;
struct foreach_arg arg;
struct getline_arg garg;
argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
extract_getline_args(argc-1, argv+1, &garg);
open_key_args(io, argc, argv, opt, &arg);
if (NIL_P(arg.io)) return Qnil;
extract_getline_opts(opt, &garg);
check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
}
Gibt ein Array aller aus dem Stream gelesenen Zeilen zurück.
Wenn diese Methode von der Klasse IO (aber nicht von Unterklassen von IO) aufgerufen wird, birgt sie potenzielle Sicherheitslücken, wenn sie mit nicht vertrauenswürdigen Eingaben aufgerufen wird; siehe Command Injection.
Das erste Argument muss ein String sein, der der Pfad zu einer Datei ist.
Wenn nur das Argument path gegeben ist, werden Zeilen aus der Datei am angegebenen path gemäß dem Standardzeilentrenner geparst und diese Zeilen in einem Array zurückgegeben.
IO.readlines('t.txt') # => ["First line\n", "Second line\n", "\n", "Third line\n", "Fourth line\n"]
Wenn das Argument sep gegeben ist, werden Zeilen wie durch diesen Zeilentrenner bestimmt geparst (siehe Zeilentrenner).
# Ordinary separator. IO.readlines('t.txt', 'li') # =>["First li", "ne\nSecond li", "ne\n\nThird li", "ne\nFourth li", "ne\n"] # Get-paragraphs separator. IO.readlines('t.txt', '') # => ["First line\nSecond line\n\n", "Third line\nFourth line\n"] # Get-all separator. IO.readlines('t.txt', nil) # => ["First line\nSecond line\n\nThird line\nFourth line\n"]
Wenn das Argument limit gegeben ist, werden Zeilen gemäß dem Standardzeilentrenner und dem angegebenen Zeilenlängenlimit geparst (siehe Zeilentrenner und Zeilenlimit).
IO.readlines('t.txt', 7) # => ["First l", "ine\n", "Second ", "line\n", "\n", "Third l", "ine\n", "Fourth ", "line\n"]
Mit den Argumenten sep und limit werden die beiden Verhaltensweisen kombiniert (siehe Zeilentrenner und Zeilenlimit).
Optionale Schlüsselwortargumente opts spezifizieren
Source
static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
// It's optionally supported.
VALUE result = rb_fiber_scheduler_io_selectv(scheduler, argc, argv);
if (!UNDEF_P(result)) return result;
}
VALUE timeout;
struct select_args args;
struct timeval timerec;
int i;
rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
if (NIL_P(timeout) || is_pos_inf(timeout)) {
args.timeout = 0;
}
else {
timerec = rb_time_interval(timeout);
args.timeout = &timerec;
}
for (i = 0; i < numberof(args.fdsets); ++i)
rb_fd_init(&args.fdsets[i]);
return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
}
Ruft den Systemaufruf select(2) auf, der mehrere Dateideskriptoren überwacht und wartet, bis einer oder mehrere der Dateideskriptoren für eine bestimmte Art von I/O-Operation bereit sind.
Nicht auf allen Plattformen implementiert.
Jedes der Argumente read_ios, write_ios und error_ios ist ein Array von IO-Objekten.
Das Argument timeout ist ein numerischer Wert (wie Integer oder Float) für das Zeitintervall in Sekunden. timeout kann auch nil oder Float::INFINITY sein. nil und Float::INFINITY bedeuten kein Timeout.
Die Methode überwacht die IO-Objekte in allen drei Arrays und wartet darauf, dass einige davon bereit sind; gibt ein 3-Element-Array zurück, dessen Elemente sind
-
Ein Array der Objekte in
read_ios, die zum Lesen bereit sind. -
Ein Array der Objekte in
write_ios, die zum Schreiben bereit sind. -
Ein Array der Objekte in
error_ios, die ausstehende Ausnahmen haben.
Wenn innerhalb des angegebenen timeout kein Objekt bereit wird, wird nil zurückgegeben.
IO.select prüft den Puffer von IO-Objekten, um die Lesebereitschaft zu testen. Wenn der IO-Puffer nicht leer ist, benachrichtigt IO.select sofort die Lesebereitschaft. Dieses „Prüfen“ geschieht nur für IO-Objekte. Es geschieht nicht für IO-ähnliche Objekte wie OpenSSL::SSL::SSLSocket.
Der beste Weg, IO.select zu verwenden, ist, es nach nicht-blockierenden Methoden wie read_nonblock, write_nonblock usw. aufzurufen. Die Methoden werfen eine Ausnahme, die von IO::WaitReadable oder IO::WaitWritable erweitert wird. Die Module benachrichtigen, wie der Aufrufer mit IO.select warten soll. Wenn IO::WaitReadable ausgelöst wird, sollte der Aufrufer auf Lesen warten. Wenn IO::WaitWritable ausgelöst wird, sollte der Aufrufer auf Schreiben warten.
Somit kann blockierendes Lesen (readpartial) mit read_nonblock und IO.select wie folgt emuliert werden:
begin result = io_like.read_nonblock(maxlen) rescue IO::WaitReadable IO.select([io_like]) retry rescue IO::WaitWritable IO.select(nil, [io_like]) retry end
Insbesondere die Kombination von nicht-blockierenden Methoden und IO.select ist für IO-ähnliche Objekte wie OpenSSL::SSL::SSLSocket vorzuziehen. Es verfügt über die Methode to_io, die das zugrunde liegende IO-Objekt zurückgibt. IO.select ruft to_io auf, um den Dateideskriptor zu erhalten, auf den gewartet werden soll.
Das bedeutet, dass die von IO.select benachrichtigte Lesebereitschaft nicht die Lesebereitschaft vom OpenSSL::SSL::SSLSocket-Objekt bedeutet.
Die wahrscheinlichste Situation ist, dass OpenSSL::SSL::SSLSocket einige Daten puffert. IO.select sieht den Puffer nicht. Daher kann IO.select blockieren, wenn OpenSSL::SSL::SSLSocket#readpartial nicht blockiert.
Es gibt jedoch mehrere kompliziertere Situationen.
SSL ist ein Protokoll, das aus einer Sequenz von Datensätzen besteht. Der Datensatz besteht aus mehreren Bytes. Daher sendet die Remote-Seite von SSL einen partiellen Datensatz, IO.select benachrichtigt die Lesebereitschaft, aber OpenSSL::SSL::SSLSocket kann kein Byte entschlüsseln und OpenSSL::SSL::SSLSocket#readpartial wird blockieren.
Außerdem kann die Remote-Seite eine SSL-Neuaushandlung anfordern, die die lokale SSL-Engine zwingt, einige Daten zu schreiben. Das bedeutet, dass OpenSSL::SSL::SSLSocket#readpartial einen write-Systemaufruf auslösen kann und dieser blockieren kann. In einer solchen Situation löst OpenSSL::SSL::SSLSocket#read_nonblock IO::WaitWritable aus, anstatt zu blockieren. Daher sollte der Aufrufer wie im obigen Beispiel auf die Schreibbereitschaft warten.
Die Kombination von nicht-blockierenden Methoden und IO.select ist auch nützlich für Streams wie TTYs, Pipe-Sockets, wenn mehrere Prozesse aus einem Stream lesen.
Schließlich garantieren die Linux-Kernel-Entwickler nicht, dass die Lesebereitschaft von select(2) die Lesebereitschaft des folgenden read(2) bedeutet, selbst für einen einzelnen Prozess; siehe select(2).
Das Aufrufen von IO.select vor IO#readpartial funktioniert wie üblich gut. Es ist jedoch nicht der beste Weg, IO.select zu verwenden.
Die von select(2) benachrichtigte Schreibbereitschaft zeigt nicht an, wie viele Bytes schreibbar sind. Die Methode IO#write blockiert, bis der gesamte angegebene String geschrieben wurde. Daher kann IO#write(zwei oder mehr Bytes) nach Benachrichtigung der Schreibbereitschaft durch IO.select blockieren. IO#write_nonblock ist erforderlich, um das Blockieren zu vermeiden.
Blockierendes Schreiben (write) kann mit write_nonblock und IO.select wie folgt emuliert werden: IO::WaitReadable sollte auch für SSL-Neuaushandlung in OpenSSL::SSL::SSLSocket abgefangen werden.
while 0 < string.bytesize begin written = io_like.write_nonblock(string) rescue IO::WaitReadable IO.select([io_like]) retry rescue IO::WaitWritable IO.select(nil, [io_like]) retry end string = string.byteslice(written..-1) end
Beispiel
rp, wp = IO.pipe mesg = "ping " 100.times { # IO.select follows IO#read. Not the best way to use IO.select. rs, ws, = IO.select([rp], [wp]) if r = rs[0] ret = r.read(5) print ret case ret when /ping/ mesg = "pong\n" when /pong/ mesg = "ping " end end if w = ws[0] w.write(mesg) end }
Ausgabe
ping pong ping pong ping pong (snipped) ping
Source
static VALUE
rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
{
VALUE fname, vmode, vperm;
VALUE intmode;
int oflags, fd;
mode_t perm;
rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
FilePathValue(fname);
if (NIL_P(vmode))
oflags = O_RDONLY;
else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
oflags = NUM2INT(intmode);
else {
StringValue(vmode);
oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
}
if (NIL_P(vperm)) perm = 0666;
else perm = NUM2MODET(vperm);
RB_GC_GUARD(fname) = rb_str_new4(fname);
fd = rb_sysopen(fname, oflags, perm);
return INT2NUM(fd);
}
Öffnet die Datei am angegebenen Pfad mit dem angegebenen Modus und Berechtigungen; gibt den ganzzahligen Dateideskriptor zurück.
Wenn die Datei lesbar sein soll, muss sie existieren; wenn die Datei beschreibbar sein soll und nicht existiert, wird sie mit den angegebenen Berechtigungen erstellt.
File.write('t.tmp', '') # => 0 IO.sysopen('t.tmp') # => 8 IO.sysopen('t.tmp', 'w') # => 9
Source
static VALUE
rb_io_s_try_convert(VALUE dummy, VALUE io)
{
return rb_io_check_io(io);
}
Versucht, object über die Methode to_io in ein IO-Objekt zu konvertieren; gibt das neue IO-Objekt zurück, wenn erfolgreich, andernfalls nil.
IO.try_convert(STDOUT) # => #<IO:<STDOUT>> IO.try_convert(ARGF) # => #<IO:<STDIN>> IO.try_convert('STDOUT') # => nil
Source
static VALUE
rb_io_s_write(int argc, VALUE *argv, VALUE io)
{
return io_s_write(argc, argv, io, 0);
}
Öffnet den Stream, schreibt die angegebenen data hinein und schließt den Stream; gibt die Anzahl der geschriebenen Bytes zurück.
Wenn diese Methode von der Klasse IO (aber nicht von Unterklassen von IO) aufgerufen wird, birgt sie potenzielle Sicherheitslücken, wenn sie mit nicht vertrauenswürdigen Eingaben aufgerufen wird; siehe Command Injection.
Das erste Argument muss ein String sein, der der Pfad zu einer Datei ist.
Wenn nur das Argument path gegeben ist, werden die angegebenen data in die Datei unter diesem Pfad geschrieben.
IO.write('t.tmp', 'abc') # => 3 File.read('t.tmp') # => "abc"
Wenn offset null ist (Standard), wird die Datei überschrieben.
IO.write('t.tmp', 'A') # => 1 File.read('t.tmp') # => "A"
Wenn offset innerhalb des Dateiinhalts liegt, wird die Datei teilweise überschrieben.
IO.write('t.tmp', 'abcdef') # => 3 File.read('t.tmp') # => "abcdef" # Offset within content. IO.write('t.tmp', '012', 2) # => 3 File.read('t.tmp') # => "ab012f"
Wenn offset außerhalb des Dateiinhalts liegt, wird die Datei mit Nullzeichen "\u0000" aufgefüllt.
IO.write('t.tmp', 'xyz', 10) # => 3 File.read('t.tmp') # => "ab012f\u0000\u0000\u0000\u0000xyz"
Optionale Schlüsselwortargumente opts spezifizieren
Öffentliche Instanzmethoden
Source
VALUE
rb_io_addstr(VALUE io, VALUE str)
{
rb_io_write(io, str);
return io;
}
Schreibt das angegebene object in self, das zum Schreiben geöffnet sein muss (siehe Zugriffsmodi); gibt self zurück; wenn object kein String ist, wird es über die Methode to_s konvertiert.
$stdout << 'Hello' << ', ' << 'World!' << "\n" $stdout << 'foo' << :bar << 2 << "\n"
Ausgabe
Hello, World! foobar2
Source
static VALUE
rb_io_advise(int argc, VALUE *argv, VALUE io)
{
VALUE advice, offset, len;
rb_off_t off, l;
rb_io_t *fptr;
rb_scan_args(argc, argv, "12", &advice, &offset, &len);
advice_arg_check(advice);
io = GetWriteIO(io);
GetOpenFile(io, fptr);
off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
l = NIL_P(len) ? 0 : NUM2OFFT(len);
#ifdef HAVE_POSIX_FADVISE
return do_io_advise(fptr, advice, off, l);
#else
((void)off, (void)l); /* Ignore all hint */
return Qnil;
#endif
}
Ruft den Posix-Systemaufruf posix_fadvise(2) auf, der eine Absicht ankündigt, auf Daten aus der aktuellen Datei auf eine bestimmte Weise zuzugreifen.
Die Argumente und Ergebnisse sind plattformabhängig.
Die relevanten Daten werden angegeben durch
-
offset: Der Offset des ersten Bytes der Daten. -
len: Die Anzahl der Bytes, auf die zugegriffen werden soll; wennlennull ist oder größer als die Anzahl der verbleibenden Bytes, wird auf alle verbleibenden Bytes zugegriffen.
Das Argument advice ist eines der folgenden Symbole
-
:normal: Die Anwendung hat keine Hinweise zur Zugriffsmuster für die angegebenen Daten. Wenn keine Hinweise für eine geöffnete Datei gegeben werden, ist dies die Standardannahme. -
:sequential: Die Anwendung erwartet, sequenziell auf die angegebenen Daten zuzugreifen (niedrigere Offsets werden vor höheren gelesen). -
:random: Auf die angegebenen Daten wird in zufälliger Reihenfolge zugegriffen. -
:noreuse: Auf die angegebenen Daten wird nur einmal zugegriffen. -
:willneed: Auf die angegebenen Daten wird in naher Zukunft zugegriffen. -
:dontneed: Auf die angegebenen Daten wird in naher Zukunft nicht zugegriffen.
Nicht auf allen Plattformen implementiert.
Source
static VALUE
rb_io_set_autoclose(VALUE io, VALUE autoclose)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
if (!RTEST(autoclose))
fptr->mode |= FMODE_EXTERNAL;
else
fptr->mode &= ~FMODE_EXTERNAL;
return autoclose;
}
Setzt das Auto-Close-Flag.
f = File.open(File::NULL) IO.for_fd(f.fileno).close f.gets # raises Errno::EBADF f = File.open(File::NULL) g = IO.for_fd(f.fileno) g.autoclose = false g.close f.gets # won't cause Errno::EBADF
Source
static VALUE
rb_io_autoclose_p(VALUE io)
{
rb_io_t *fptr = RFILE(io)->fptr;
rb_io_check_closed(fptr);
return RBOOL(!(fptr->mode & FMODE_EXTERNAL));
}
Gibt true zurück, wenn der zugrunde liegende Dateideskriptor von ios bei seiner Finalisierung oder beim Aufruf von close geschlossen wird, andernfalls false.
Source
static VALUE
console_beep(VALUE io)
{
#ifdef _WIN32
MessageBeep(0);
#else
int fd = GetWriteFD(io);
if (write(fd, "\a", 1) < 0) sys_fail(io);
#endif
return io;
}
Gibt einen Piepton auf der Ausgabekonsole aus.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
rb_io_binmode_m(VALUE io)
{
VALUE write_io;
rb_io_ascii8bit_binmode(io);
write_io = GetWriteIO(io);
if (write_io != io)
rb_io_ascii8bit_binmode(write_io);
return io;
}
Setzt den Datenmodus des Streams auf binär (siehe Datenmodus).
Ein Datenmodus eines Streams kann nicht von binär auf Text geändert werden.
Source
static VALUE
rb_io_binmode_p(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
return RBOOL(fptr->mode & FMODE_BINMODE);
}
Gibt true zurück, wenn der Stream im Binärmodus ist, andernfalls false. Siehe Datenmodus.
Source
static VALUE
console_check_winsize_changed(VALUE io)
{
HANDLE h;
DWORD num;
h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) {
INPUT_RECORD rec;
if (ReadConsoleInput(h, &rec, 1, &num)) {
if (rec.EventType == WINDOW_BUFFER_SIZE_EVENT) {
rb_yield(Qnil);
}
}
}
return io;
}
Wartet, während Konsoleneingabeereignisse in der Warteschlange stehen.
Diese Methode ist nur für Windows verfügbar.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_clear_screen(VALUE io)
{
console_erase_screen(io, INT2FIX(2));
console_goto(io, INT2FIX(0), INT2FIX(0));
return io;
}
Löscht den gesamten Bildschirm und bewegt den Cursor zur oberen linken Ecke.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
rb_io_close_m(VALUE io)
{
rb_io_t *fptr = rb_io_get_fptr(io);
if (fptr->fd < 0) {
return Qnil;
}
rb_io_close(io);
return Qnil;
}
Schließt den Stream sowohl für das Lesen als auch für das Schreiben, wenn er für eines oder beides geöffnet ist; gibt nil zurück. Siehe Geöffnete und geschlossene Streams.
Wenn der Stream zum Schreiben geöffnet war, werden alle gepufferten Schreibvorgänge vor dem Schließen an das Betriebssystem geleert.
Wenn der Stream von IO.popen geöffnet wurde, wird die globale Variable $? (Exit-Status des Kindes) gesetzt.
Es ist kein Fehler, ein IO-Objekt zu schließen, das bereits geschlossen wurde. Es gibt einfach nil zurück.
Beispiel
IO.popen('ruby', 'r+') do |pipe| puts pipe.closed? pipe.close puts $? puts pipe.closed? end
Ausgabe
false pid 13760 exit 0 true
Zugehörig: IO#close_read, IO#close_write, IO#closed?.
Source
static VALUE
rb_io_set_close_on_exec(VALUE io, VALUE arg)
{
int flag = RTEST(arg) ? FD_CLOEXEC : 0;
rb_io_t *fptr;
VALUE write_io;
int fd, ret;
write_io = GetWriteIO(io);
if (io != write_io) {
GetOpenFile(write_io, fptr);
if (fptr && 0 <= (fd = fptr->fd)) {
if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
if ((ret & FD_CLOEXEC) != flag) {
ret = (ret & ~FD_CLOEXEC) | flag;
ret = fcntl(fd, F_SETFD, ret);
if (ret != 0) rb_sys_fail_path(fptr->pathv);
}
}
}
GetOpenFile(io, fptr);
if (fptr && 0 <= (fd = fptr->fd)) {
if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
if ((ret & FD_CLOEXEC) != flag) {
ret = (ret & ~FD_CLOEXEC) | flag;
ret = fcntl(fd, F_SETFD, ret);
if (ret != 0) rb_sys_fail_path(fptr->pathv);
}
}
return Qnil;
}
Setzt ein Close-on-Exec-Flag.
f = File.open(File::NULL) f.close_on_exec = true system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory f.closed? #=> false
Ruby setzt standardmäßig Close-on-Exec-Flags aller Dateideskriptoren seit Ruby 2.0.0. Daher müssen Sie diese nicht selbst setzen. Außerdem kann das Aufheben eines Close-on-Exec-Flags zu einem Dateideskriptor-Leak führen, wenn ein anderer Thread fork() und exec() verwendet (z. B. über die system()-Methode). Wenn Sie wirklich eine Vererbung des Dateideskriptors an einen Kindprozess benötigen, verwenden Sie Argumente wie fd=>fd von spawn().
Source
static VALUE
rb_io_close_on_exec_p(VALUE io)
{
rb_io_t *fptr;
VALUE write_io;
int fd, ret;
write_io = GetWriteIO(io);
if (io != write_io) {
GetOpenFile(write_io, fptr);
if (fptr && 0 <= (fd = fptr->fd)) {
if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
if (!(ret & FD_CLOEXEC)) return Qfalse;
}
}
GetOpenFile(io, fptr);
if (fptr && 0 <= (fd = fptr->fd)) {
if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
if (!(ret & FD_CLOEXEC)) return Qfalse;
}
return Qtrue;
}
Gibt true zurück, wenn der Stream bei exec geschlossen wird, andernfalls false.
f = File.open('t.txt') f.close_on_exec? # => true f.close_on_exec = false f.close_on_exec? # => false f.close
Source
static VALUE
rb_io_close_read(VALUE io)
{
rb_io_t *fptr;
VALUE write_io;
fptr = rb_io_get_fptr(rb_io_taint_check(io));
if (fptr->fd < 0) return Qnil;
if (is_socket(fptr->fd, fptr->pathv)) {
#ifndef SHUT_RD
# define SHUT_RD 0
#endif
if (shutdown(fptr->fd, SHUT_RD) < 0)
rb_sys_fail_path(fptr->pathv);
fptr->mode &= ~FMODE_READABLE;
if (!(fptr->mode & FMODE_WRITABLE))
return rb_io_close(io);
return Qnil;
}
write_io = GetWriteIO(io);
if (io != write_io) {
rb_io_t *wfptr;
wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
wfptr->pid = fptr->pid;
fptr->pid = 0;
RFILE(io)->fptr = wfptr;
/* bind to write_io temporarily to get rid of memory/fd leak */
fptr->tied_io_for_writing = 0;
RFILE(write_io)->fptr = fptr;
rb_io_fptr_cleanup(fptr, FALSE);
/* should not finalize fptr because another thread may be reading it */
return Qnil;
}
if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
rb_raise(rb_eIOError, "closing non-duplex IO for reading");
}
return rb_io_close(io);
}
Schließt den Stream zum Lesen, wenn er zum Lesen geöffnet ist; gibt nil zurück. Siehe Geöffnete und geschlossene Streams.
Wenn der Stream von IO.popen geöffnet wurde und auch zum Schreiben geschlossen ist, wird die globale Variable $? (Exit-Status des Kindes) gesetzt.
Beispiel
IO.popen('ruby', 'r+') do |pipe| puts pipe.closed? pipe.close_write puts pipe.closed? pipe.close_read puts $? puts pipe.closed? end
Ausgabe
false false pid 14748 exit 0 true
Zugehörig: IO#close, IO#close_write, IO#closed?.
Source
static VALUE
rb_io_close_write(VALUE io)
{
rb_io_t *fptr;
VALUE write_io;
write_io = GetWriteIO(io);
fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
if (fptr->fd < 0) return Qnil;
if (is_socket(fptr->fd, fptr->pathv)) {
#ifndef SHUT_WR
# define SHUT_WR 1
#endif
if (shutdown(fptr->fd, SHUT_WR) < 0)
rb_sys_fail_path(fptr->pathv);
fptr->mode &= ~FMODE_WRITABLE;
if (!(fptr->mode & FMODE_READABLE))
return rb_io_close(write_io);
return Qnil;
}
if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
rb_raise(rb_eIOError, "closing non-duplex IO for writing");
}
if (io != write_io) {
fptr = rb_io_get_fptr(rb_io_taint_check(io));
fptr->tied_io_for_writing = 0;
}
rb_io_close(write_io);
return Qnil;
}
Schließt den Stream zum Schreiben, wenn er zum Schreiben geöffnet ist; gibt nil zurück. Siehe Geöffnete und geschlossene Streams.
Leert alle gepufferten Schreibvorgänge vor dem Schließen in das Betriebssystem.
Wenn der Stream von IO.popen geöffnet wurde und auch zum Lesen geschlossen ist, wird die globale Variable $? (Exit-Status des Kindes) gesetzt.
IO.popen('ruby', 'r+') do |pipe| puts pipe.closed? pipe.close_read puts pipe.closed? pipe.close_write puts $? puts pipe.closed? end
Ausgabe
false false pid 15044 exit 0 true
Zugehörig: IO#close, IO#close_read, IO#closed?.
Source
VALUE
rb_io_closed_p(VALUE io)
{
rb_io_t *fptr;
VALUE write_io;
rb_io_t *write_fptr;
write_io = GetWriteIO(io);
if (io != write_io) {
write_fptr = RFILE(write_io)->fptr;
if (write_fptr && 0 <= write_fptr->fd) {
return Qfalse;
}
}
fptr = rb_io_get_fptr(io);
return RBOOL(0 > fptr->fd);
}
Gibt true zurück, wenn der Stream sowohl für das Lesen als auch für das Schreiben geschlossen ist, andernfalls false. Siehe Geöffnete und geschlossene Streams.
IO.popen('ruby', 'r+') do |pipe| puts pipe.closed? pipe.close_read puts pipe.closed? pipe.close_write puts pipe.closed? end
Ausgabe
false false true
Zugehörig: IO#close_read, IO#close_write, IO#close.
Source
static VALUE
console_conmode_get(VALUE io)
{
conmode t;
int fd = GetReadFD(io);
if (!getattr(fd, &t)) sys_fail(io);
return conmode_new(cConmode, &t);
}
Gibt die aktuellen Konsolenmodi als Daten zurück.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_conmode_set(VALUE io, VALUE mode)
{
conmode *t, r;
int fd = GetReadFD(io);
TypedData_Get_Struct(mode, conmode, &conmode_type, t);
r = *t;
if (!setattr(fd, &r)) sys_fail(io);
return mode;
}
Setzt den Konsolenmodus auf mode.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_cooked(VALUE io)
{
return ttymode(io, rb_yield, io, set_cookedmode, NULL);
}
Yielded self im Cooked-Modus.
STDIN.cooked(&:gets)
Liest und gibt eine Zeile mit Echo und Zeilenbearbeitung zurück.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_set_cooked(VALUE io)
{
conmode t;
int fd = GetReadFD(io);
if (!getattr(fd, &t)) sys_fail(io);
set_cookedmode(&t, NULL);
if (!setattr(fd, &t)) sys_fail(io);
return io;
}
Aktiviert den Cooked-Modus.
Wenn der Terminalmodus wiederhergestellt werden muss, verwenden Sie io.cooked { … }.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_cursor_pos(VALUE io)
{
#ifdef _WIN32
rb_console_size_t ws;
int fd = GetWriteFD(io);
if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
rb_syserr_fail(LAST_ERROR, 0);
}
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y - ws.srWindow.Top), UINT2NUM(ws.dwCursorPosition.X));
#else
static const struct query_args query = {"\033[6n", 0};
VALUE resp = console_vt_response(0, 0, io, &query);
VALUE row, column, term;
unsigned int r, c;
if (!RB_TYPE_P(resp, T_ARRAY) || RARRAY_LEN(resp) != 3) return Qnil;
term = RARRAY_AREF(resp, 2);
if (!RB_TYPE_P(term, T_STRING) || RSTRING_LEN(term) != 1) return Qnil;
if (RSTRING_PTR(term)[0] != 'R') return Qnil;
row = RARRAY_AREF(resp, 0);
column = RARRAY_AREF(resp, 1);
rb_ary_resize(resp, 2);
r = NUM2UINT(row) - 1;
c = NUM2UINT(column) - 1;
RARRAY_ASET(resp, 0, INT2NUM(r));
RARRAY_ASET(resp, 1, INT2NUM(c));
return resp;
#endif
}
Gibt die aktuelle Cursorposition als Zwei-Element-Array von Integers (Zeile, Spalte) zurück.
io.cursor # => [3, 5]
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_cursor_set(VALUE io, VALUE cpos)
{
cpos = rb_convert_type(cpos, T_ARRAY, "Array", "to_ary");
if (RARRAY_LEN(cpos) != 2) rb_raise(rb_eArgError, "expected 2D coordinate");
return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1));
}
Identisch mit io.goto(line, column).
Siehe IO#goto.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_cursor_down(VALUE io, VALUE val)
{
return console_move(io, +NUM2INT(val), 0);
}
Bewegt den Cursor um n Zeilen nach unten.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_cursor_left(VALUE io, VALUE val)
{
return console_move(io, 0, -NUM2INT(val));
}
Bewegt den Cursor um n Spalten nach links.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_cursor_right(VALUE io, VALUE val)
{
return console_move(io, 0, +NUM2INT(val));
}
Bewegt den Cursor um n Spalten nach rechts.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_cursor_up(VALUE io, VALUE val)
{
return console_move(io, -NUM2INT(val), 0);
}
Bewegt den Cursor um n Zeilen nach oben.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
VALUE str;
struct getline_arg args;
RETURN_ENUMERATOR(io, argc, argv);
prepare_getline_args(argc, argv, &args, io);
if (args.limit == 0)
rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
rb_yield(str);
}
return io;
}
Source
static VALUE
rb_io_each_byte(VALUE io)
{
rb_io_t *fptr;
RETURN_ENUMERATOR(io, 0, 0);
GetOpenFile(io, fptr);
do {
while (fptr->rbuf.len > 0) {
char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
fptr->rbuf.len--;
rb_yield(INT2FIX(*p & 0xff));
rb_io_check_byte_readable(fptr);
errno = 0;
}
READ_CHECK(fptr);
} while (io_fillbuf(fptr) >= 0);
return io;
}
Ruft den angegebenen Block für jedes Byte (0..255) im Stream auf; gibt self zurück. Siehe Byte IO.
f = File.new('t.rus') a = [] f.each_byte {|b| a << b } a # => [209, 130, 208, 181, 209, 129, 209, 130] f.close
Gibt einen Enumerator zurück, wenn kein Block gegeben ist.
Zugehörig: IO#each_char, IO#each_codepoint.
Source
static VALUE
rb_io_each_char(VALUE io)
{
rb_io_t *fptr;
rb_encoding *enc;
VALUE c;
RETURN_ENUMERATOR(io, 0, 0);
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
enc = io_input_encoding(fptr);
READ_CHECK(fptr);
while (!NIL_P(c = io_getc(fptr, enc))) {
rb_yield(c);
}
return io;
}
Ruft den angegebenen Block für jedes Zeichen im Stream auf; gibt self zurück. Siehe Character IO.
f = File.new('t.rus') a = [] f.each_char {|c| a << c.ord } a # => [1090, 1077, 1089, 1090] f.close
Gibt einen Enumerator zurück, wenn kein Block gegeben ist.
Zugehörig: IO#each_byte, IO#each_codepoint.
Source
static VALUE
rb_io_each_codepoint(VALUE io)
{
rb_io_t *fptr;
rb_encoding *enc;
unsigned int c;
int r, n;
RETURN_ENUMERATOR(io, 0, 0);
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
READ_CHECK(fptr);
enc = io_read_encoding(fptr);
if (NEED_READCONV(fptr)) {
SET_BINARY_MODE(fptr);
r = 1; /* no invalid char yet */
for (;;) {
make_readconv(fptr, 0);
for (;;) {
if (fptr->cbuf.len) {
r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
enc);
if (!MBCLEN_NEEDMORE_P(r))
break;
if (fptr->cbuf.len == fptr->cbuf.capa) {
rb_raise(rb_eIOError, "too long character");
}
}
if (more_char(fptr) == MORE_CHAR_FINISHED) {
clear_readconv(fptr);
if (!MBCLEN_CHARFOUND_P(r)) {
goto invalid;
}
return io;
}
}
if (MBCLEN_INVALID_P(r)) {
goto invalid;
}
n = MBCLEN_CHARFOUND_LEN(r);
c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
enc);
fptr->cbuf.off += n;
fptr->cbuf.len -= n;
rb_yield(UINT2NUM(c));
rb_io_check_char_readable(fptr);
}
}
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
while (io_fillbuf(fptr) >= 0) {
r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
if (MBCLEN_CHARFOUND_P(r) &&
(n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
fptr->rbuf.off += n;
fptr->rbuf.len -= n;
rb_yield(UINT2NUM(c));
}
else if (MBCLEN_INVALID_P(r)) {
goto invalid;
}
else if (MBCLEN_NEEDMORE_P(r)) {
char cbuf[8], *p = cbuf;
int more = MBCLEN_NEEDMORE_LEN(r);
if (more > numberof(cbuf)) goto invalid;
more += n = fptr->rbuf.len;
if (more > numberof(cbuf)) goto invalid;
while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
(p += n, (more -= n) > 0)) {
if (io_fillbuf(fptr) < 0) goto invalid;
if ((n = fptr->rbuf.len) > more) n = more;
}
r = rb_enc_precise_mbclen(cbuf, p, enc);
if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
c = rb_enc_codepoint(cbuf, p, enc);
rb_yield(UINT2NUM(c));
}
else {
continue;
}
rb_io_check_byte_readable(fptr);
}
return io;
invalid:
rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
UNREACHABLE_RETURN(Qundef);
}
Ruft den angegebenen Block für jeden Codepoint im Stream auf; gibt self zurück.
f = File.new('t.rus') a = [] f.each_codepoint {|c| a << c } a # => [1090, 1077, 1089, 1090] f.close
Gibt einen Enumerator zurück, wenn kein Block gegeben ist.
Zugehörig: IO#each_byte, IO#each_char.
Ruft den Block mit jeder verbleibenden Zeile auf, die aus dem Stream gelesen wird; gibt self zurück. Tut nichts, wenn bereits am Stream-Ende; siehe Line IO.
Wenn keine Argumente gegeben sind, werden Zeilen gemäß dem Zeilentrenner $/ gelesen.
f = File.new('t.txt') f.each_line {|line| p line } f.each_line {|line| fail 'Cannot happen' } f.close
Ausgabe
"First line\n" "Second line\n" "\n" "Fourth line\n" "Fifth line\n"
Wenn nur das String-Argument sep gegeben ist, werden Zeilen gemäß dem Zeilentrenner sep gelesen; siehe Zeilentrenner.
f = File.new('t.txt') f.each_line('li') {|line| p line } f.close
Ausgabe
"First li" "ne\nSecond li" "ne\n\nFourth li" "ne\nFifth li" "ne\n"
Die beiden Sonderwerte für sep werden berücksichtigt.
f = File.new('t.txt') # Get all into one string. f.each_line(nil) {|line| p line } f.close
Ausgabe
"First line\nSecond line\n\nFourth line\nFifth line\n" f.rewind # Get paragraphs (up to two line separators). f.each_line('') {|line| p line }
Ausgabe
"First line\nSecond line\n\n" "Fourth line\nFifth line\n"
Wenn nur das Integer-Argument limit gegeben ist, wird die Anzahl der Bytes pro Zeile begrenzt; siehe Zeilenlimit.
f = File.new('t.txt') f.each_line(8) {|line| p line } f.close
Ausgabe
"First li" "ne\n" "Second l" "ine\n" "\n" "Fourth l" "ine\n" "Fifth li" "ne\n"
Mit den Argumenten sep und limit werden die beiden Verhaltensweisen kombiniert (siehe Zeilentrenner und Zeilenlimit).
Das optionale Schlüsselwortargument chomp gibt an, ob Zeilentrenner weggelassen werden sollen.
f = File.new('t.txt') f.each_line(chomp: true) {|line| p line } f.close
Ausgabe
"First line" "Second line" "" "Fourth line" "Fifth line"
Gibt einen Enumerator zurück, wenn kein Block gegeben ist.
Source
static VALUE
console_set_echo(VALUE io, VALUE f)
{
conmode t;
int fd = GetReadFD(io);
if (!getattr(fd, &t)) sys_fail(io);
if (RTEST(f))
set_echo(&t, NULL);
else
set_noecho(&t, NULL);
if (!setattr(fd, &t)) sys_fail(io);
return io;
}
Schaltet die Echo-Wiedergabe ein/aus. Auf einigen Plattformen sind möglicherweise nicht alle Kombinationen dieser Flags und des Raw/Cooked-Modus gültig.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_echo_p(VALUE io)
{
conmode t;
int fd = GetReadFD(io);
if (!getattr(fd, &t)) sys_fail(io);
return echo_p(&t) ? Qtrue : Qfalse;
}
Gibt true zurück, wenn die Echo-Wiedergabe aktiviert ist.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
VALUE
rb_io_eof(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
if (READ_CHAR_PENDING(fptr)) return Qfalse;
if (READ_DATA_PENDING(fptr)) return Qfalse;
READ_CHECK(fptr);
#if RUBY_CRLF_ENVIRONMENT
if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
return RBOOL(eof(fptr->fd));
}
#endif
return RBOOL(io_fillbuf(fptr) < 0);
}
Gibt true zurück, wenn der Stream am Ende positioniert ist, andernfalls false; siehe Position.
f = File.open('t.txt') f.eof # => false f.seek(0, :END) # => 0 f.eof # => true f.close
Wirft eine Ausnahme, es sei denn, der Stream ist zum Lesen geöffnet; siehe Modus.
Wenn self ein Stream wie eine Pipe oder ein Socket ist, blockiert diese Methode, bis das andere Ende einige Daten sendet oder ihn schließt.
r, w = IO.pipe Thread.new { sleep 1; w.close } r.eof? # => true # After 1-second wait. r, w = IO.pipe Thread.new { sleep 1; w.puts "a" } r.eof? # => false # After 1-second wait. r, w = IO.pipe r.eof? # blocks forever
Beachten Sie, dass diese Methode Daten in den Eingabe-Bytepuffer liest. Daher verhält sich IO#sysread möglicherweise nicht wie beabsichtigt mit IO#eof?, es sei denn, Sie rufen zuerst IO#rewind auf (was für einige Streams nicht verfügbar ist).
Source
static VALUE
console_erase_line(VALUE io, VALUE val)
{
int mode = mode_in_range(val, 2, "line erase");
#ifdef _WIN32
HANDLE h;
rb_console_size_t ws;
COORD *pos = &ws.dwCursorPosition;
DWORD w;
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
if (!GetConsoleScreenBufferInfo(h, &ws)) {
rb_syserr_fail(LAST_ERROR, 0);
}
w = winsize_col(&ws);
switch (mode) {
case 0: /* after cursor */
w -= pos->X;
break;
case 1: /* before *and* cursor */
w = pos->X + 1;
pos->X = 0;
break;
case 2: /* entire line */
pos->X = 0;
break;
}
constat_clear(h, ws.wAttributes, w, *pos);
return io;
#else
rb_io_write(io, rb_sprintf(CSI "%dK", mode));
#endif
return io;
}
Löscht die Zeile am Cursor entsprechend mode. mode kann eines der folgenden sein: 0: nach dem Cursor 1: vor und Cursor 2: gesamte Zeile
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_erase_screen(VALUE io, VALUE val)
{
int mode = mode_in_range(val, 3, "screen erase");
#ifdef _WIN32
HANDLE h;
rb_console_size_t ws;
COORD *pos = &ws.dwCursorPosition;
DWORD w;
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
if (!GetConsoleScreenBufferInfo(h, &ws)) {
rb_syserr_fail(LAST_ERROR, 0);
}
w = winsize_col(&ws);
switch (mode) {
case 0: /* erase after cursor */
w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
break;
case 1: /* erase before *and* cursor */
w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
pos->X = 0;
pos->Y = ws.srWindow.Top;
break;
case 2: /* erase entire screen */
w = (w * winsize_row(&ws));
pos->X = 0;
pos->Y = ws.srWindow.Top;
break;
case 3: /* erase entire screen */
w = (w * ws.dwSize.Y);
pos->X = 0;
pos->Y = 0;
break;
}
constat_clear(h, ws.wAttributes, w, *pos);
#else
rb_io_write(io, rb_sprintf(CSI "%dJ", mode));
#endif
return io;
}
Löscht den Bildschirm am Cursor entsprechend mode. mode kann eines der folgenden sein: 0: nach dem Cursor 1: vor und Cursor 2: gesamter Bildschirm
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
# File ext/pty/lib/expect.rb, line 33 def expect(pat,timeout=9999999) buf = ''.dup case pat when String e_pat = Regexp.new(Regexp.quote(pat)) when Regexp e_pat = pat else raise TypeError, "unsupported pattern class: #{pat.class}" end @unusedBuf ||= '' while true if not @unusedBuf.empty? c = @unusedBuf.slice!(0) elsif !IO.select([self],nil,nil,timeout) or eof? then result = nil @unusedBuf = buf break else c = getc end buf << c if $expect_verbose STDOUT.print c STDOUT.flush end if mat=e_pat.match(buf) then result = [buf,*mat.captures] break end end if block_given? then yield result else return result end nil end
Die Bibliothek expect fügt die Instanzmethode IO#expect hinzu, die der TCL expect extension ähnelt.
Um diese Methode zu verwenden, müssen Sie expect anfordern.
require 'expect'
Liest aus dem IO, bis das angegebene pattern übereinstimmt oder der timeout abgelaufen ist.
Gibt ein Array mit dem gelesenen Puffer zurück, gefolgt von den Übereinstimmungen. Wenn ein Block gegeben ist, wird das Ergebnis an den Block übergeben und nil zurückgegeben.
Wenn sie ohne Block aufgerufen wird, wartet sie, bis die Eingabe, die mit dem angegebenen pattern übereinstimmt, aus dem IO erhalten wird oder die als Timeout angegebene Zeit abläuft. Ein Array wird zurückgegeben, wenn das Muster aus dem IO erhalten wird. Das erste Element des Arrays ist der gesamte String, der aus dem IO bis zum Musterergebnis erhalten wurde, gefolgt von Elementen, die angeben, welches Muster dem Anker im regulären Ausdruck entsprach.
Der optionale Timeout-Parameter definiert in Sekunden die Gesamtzeit, die auf das Muster gewartet wird. Wenn der Timeout abläuft oder EOF gefunden wird, wird nil zurückgegeben oder übergeben. Der Puffer in einer Timeout-Sitzung wird jedoch für den nächsten expect-Aufruf beibehalten. Der Standard-Timeout beträgt 9999999 Sekunden.
Source
static VALUE
rb_io_external_encoding(VALUE io)
{
rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
if (fptr->encs.enc2) {
return rb_enc_from_encoding(fptr->encs.enc2);
}
if (fptr->mode & FMODE_WRITABLE) {
if (fptr->encs.enc)
return rb_enc_from_encoding(fptr->encs.enc);
return Qnil;
}
return rb_enc_from_encoding(io_read_encoding(fptr));
}
Source
static VALUE
rb_io_fcntl(int argc, VALUE *argv, VALUE io)
{
VALUE req, arg;
rb_scan_args(argc, argv, "11", &req, &arg);
return rb_fcntl(io, req, arg);
}
Ruft den Posix-Systemaufruf fcntl(2) auf, der einen Mechanismus zur Durchführung von Low-Level-Befehlen zur Steuerung oder Abfrage eines dateiorientierten I/O-Streams bereitstellt. Argumente und Ergebnisse sind plattformabhängig.
Wenn argument eine Zahl ist, wird sein Wert direkt übergeben; wenn es ein String ist, wird er als binäre Bytefolge interpretiert. (Array#pack kann eine nützliche Möglichkeit sein, diesen String zu erstellen.)
Nicht auf allen Plattformen implementiert.
Source
static VALUE
rb_io_fdatasync(VALUE io)
{
rb_io_t *fptr;
io = GetWriteIO(io);
GetOpenFile(io, fptr);
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
if ((int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
return INT2FIX(0);
/* fall back */
return rb_io_fsync(io);
}
Schreibt sofort alle im Stream gepufferten Daten auf die Festplatte, über das Betriebssystem: fdatasync(2), wenn unterstützt, andernfalls über fsync(2), wenn unterstützt; andernfalls wird eine Ausnahme ausgelöst.
Source
static VALUE
rb_io_fileno(VALUE io)
{
rb_io_t *fptr = RFILE(io)->fptr;
int fd;
rb_io_check_closed(fptr);
fd = fptr->fd;
return INT2FIX(fd);
}
Gibt den ganzzahligen Dateideskriptor für den Stream zurück.
$stdin.fileno # => 0 $stdout.fileno # => 1 $stderr.fileno # => 2 File.open('t.txt').fileno # => 10 f.close
Source
VALUE
rb_io_flush(VALUE io)
{
return rb_io_flush_raw(io, 1);
}
Leert im self gepufferte Daten in das Betriebssystem (garantiert aber nicht, dass Daten im Betriebssystem gepuffert werden).
$stdout.print 'no newline' # Not necessarily flushed. $stdout.flush # Flushed.
Source
static VALUE
rb_io_fsync(VALUE io)
{
rb_io_t *fptr;
io = GetWriteIO(io);
GetOpenFile(io, fptr);
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
if ((int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
rb_sys_fail_path(fptr->pathv);
return INT2FIX(0);
}
Schreibt sofort alle im Stream gepufferten Daten auf die Festplatte, über das Betriebssystem fsync(2).
Beachten Sie diesen Unterschied
-
IO#sync=: Stellt sicher, dass Daten aus den internen Puffern des Streams geleert werden, garantiert aber nicht, dass das Betriebssystem die Daten tatsächlich auf die Festplatte schreibt. -
IO#fsync: Stellt sicher, dass sowohl Daten aus internen Puffern geleert als auch Daten auf die Festplatte geschrieben werden.
Löst eine Ausnahme aus, wenn das Betriebssystem fsync(2) nicht unterstützt.
Source
VALUE
rb_io_getbyte(VALUE io)
{
rb_io_t *fptr;
int c;
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
READ_CHECK(fptr);
VALUE r_stdout = rb_ractor_stdout();
if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(r_stdout, T_FILE)) {
rb_io_t *ofp;
GetOpenFile(r_stdout, ofp);
if (ofp->mode & FMODE_TTY) {
rb_io_flush(r_stdout);
}
}
if (io_fillbuf(fptr) < 0) {
return Qnil;
}
fptr->rbuf.off++;
fptr->rbuf.len--;
c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
return INT2FIX(c & 0xff);
}
Liest und gibt das nächste Byte (im Bereich 0..255) aus dem Stream zurück; gibt nil zurück, wenn bereits am Stream-Ende. Siehe Byte IO.
f = File.open('t.txt') f.getbyte # => 70 f.close f = File.open('t.rus') f.getbyte # => 209 f.close
Zugehörig: IO#readbyte (kann EOFError auslösen).
Source
static VALUE
rb_io_getc(VALUE io)
{
rb_io_t *fptr;
rb_encoding *enc;
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
enc = io_input_encoding(fptr);
READ_CHECK(fptr);
return io_getc(fptr, enc);
}
Liest und gibt den nächsten 1-Zeichen-String aus dem Stream zurück; gibt nil zurück, wenn bereits am Stream-Ende. Siehe Character IO.
f = File.open('t.txt') f.getc # => "F" f.close f = File.open('t.rus') f.getc.ord # => 1090 f.close
Zugehörig: IO#readchar (kann EOFError auslösen).
Source
static VALUE
console_getch(int argc, VALUE *argv, VALUE io)
{
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
#ifndef _WIN32
return ttymode(io, getc_call, io, set_rawmode, optp);
#else
rb_io_t *fptr;
VALUE str;
wint_t c;
int len;
char buf[8];
wint_t wbuf[2];
# ifndef HAVE_RB_IO_WAIT
struct timeval *to = NULL, tv;
# else
VALUE timeout = Qnil;
# endif
GetOpenFile(io, fptr);
if (optp) {
if (optp->vtime) {
# ifndef HAVE_RB_IO_WAIT
to = &tv;
# else
struct timeval tv;
# endif
tv.tv_sec = optp->vtime / 10;
tv.tv_usec = (optp->vtime % 10) * 100000;
# ifdef HAVE_RB_IO_WAIT
timeout = rb_fiber_scheduler_make_timeout(&tv);
# endif
}
switch (optp->vmin) {
case 1: /* default */
break;
case 0: /* return nil when timed out */
if (optp->vtime) break;
/* fallthru */
default:
rb_warning("min option larger than 1 ignored");
}
if (optp->intr) {
# ifndef HAVE_RB_IO_WAIT
int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
if (w < 0) rb_eof_error();
if (!(w & RB_WAITFD_IN)) return Qnil;
# else
VALUE result = rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), timeout);
if (!RTEST(result)) return Qnil;
# endif
}
else if (optp->vtime) {
rb_warning("Non-zero vtime option ignored if intr flag is unset");
}
}
len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0);
switch (len) {
case 0:
return Qnil;
case 2:
buf[0] = (char)wbuf[0];
c = wbuf[1];
len = 1;
do {
buf[len++] = (unsigned char)c;
} while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
return rb_str_new(buf, len);
default:
c = wbuf[0];
len = rb_uv_to_utf8(buf, c);
str = rb_utf8_str_new(buf, len);
return rb_str_conv_enc(str, NULL, rb_default_external_encoding());
}
#endif
}
Liest und gibt ein Zeichen im Raw-Modus zurück.
Siehe IO#raw für Details zu den Parametern.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_getpass(int argc, VALUE *argv, VALUE io)
{
VALUE str, wio;
rb_check_arity(argc, 0, 1);
wio = rb_io_get_write_io(io);
if (wio == io && io == rb_stdin) wio = rb_stderr;
prompt(argc, argv, wio);
rb_io_flush(wio);
str = rb_ensure(getpass_call, io, puts_call, wio);
return str_chomp(str);
}
Liest und gibt eine Zeile ohne Echo zurück. Gibt prompt aus, es sei denn, es ist nil.
Das Zeilenendezeichen, das die gelesene Zeile beendet, wird aus dem zurückgegebenen String entfernt, siehe String#chomp!.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
require 'io/console' IO::console.getpass("Enter password:") Enter password: # => "mypassword"
Source
static VALUE
rb_io_gets_m(int argc, VALUE *argv, VALUE io)
{
VALUE str;
str = rb_io_getline(argc, argv, io);
rb_lastline_set(str);
return str;
}
Liest und gibt eine Zeile aus dem Stream zurück; weist den Rückgabewert $_ zu. Siehe Line IO.
Wenn keine Argumente gegeben sind, wird die nächste Zeile gemäß dem Zeilentrenner $/ zurückgegeben, oder nil, wenn keine vorhanden ist.
f = File.open('t.txt') f.gets # => "First line\n" $_ # => "First line\n" f.gets # => "\n" f.gets # => "Fourth line\n" f.gets # => "Fifth line\n" f.gets # => nil f.close
Wenn nur das String-Argument sep gegeben ist, wird die nächste Zeile gemäß dem Zeilentrenner sep zurückgegeben, oder nil, wenn keine vorhanden ist; siehe Zeilentrenner.
f = File.new('t.txt') f.gets('l') # => "First l" f.gets('li') # => "ine\nSecond li" f.gets('lin') # => "ne\n\nFourth lin" f.gets # => "e\n" f.close
Die beiden Sonderwerte für sep werden berücksichtigt.
f = File.new('t.txt') # Get all. f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.rewind # Get paragraph (up to two line separators). f.gets('') # => "First line\nSecond line\n\n" f.close
Wenn nur das Integer-Argument limit gegeben ist, wird die Anzahl der Bytes in der Zeile begrenzt; siehe Zeilenlimit.
# No more than one line. File.open('t.txt') {|f| f.gets(10) } # => "First line" File.open('t.txt') {|f| f.gets(11) } # => "First line\n" File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
Mit den Argumenten sep und limit werden die beiden Verhaltensweisen kombiniert (siehe Zeilentrenner und Zeilenlimit).
Das optionale Schlüsselwortargument chomp gibt an, ob Zeilentrenner weggelassen werden sollen.
f = File.open('t.txt') # Chomp the lines. f.gets(chomp: true) # => "First line" f.gets(chomp: true) # => "Second line" f.gets(chomp: true) # => "" f.gets(chomp: true) # => "Fourth line" f.gets(chomp: true) # => "Fifth line" f.gets(chomp: true) # => nil f.close
Source
static VALUE
console_goto(VALUE io, VALUE y, VALUE x)
{
#ifdef _WIN32
HANDLE h;
rb_console_size_t ws;
COORD *pos = &ws.dwCursorPosition;
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
if (!GetConsoleScreenBufferInfo(h, &ws)) {
rb_syserr_fail(LAST_ERROR, 0);
}
pos->X = NUM2UINT(x);
pos->Y = ws.srWindow.Top + NUM2UINT(y);
if (!SetConsoleCursorPosition(h, *pos)) {
rb_syserr_fail(LAST_ERROR, 0);
}
#else
rb_io_write(io, rb_sprintf(CSI "%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1));
#endif
return io;
}
Setzt die Cursorposition auf line und column.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_goto_column(VALUE io, VALUE val)
{
#ifdef _WIN32
HANDLE h;
rb_console_size_t ws;
COORD *pos = &ws.dwCursorPosition;
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
if (!GetConsoleScreenBufferInfo(h, &ws)) {
rb_syserr_fail(LAST_ERROR, 0);
}
pos->X = NUM2INT(val);
if (!SetConsoleCursorPosition(h, *pos)) {
rb_syserr_fail(LAST_ERROR, 0);
}
#else
rb_io_write(io, rb_sprintf(CSI "%dG", NUM2UINT(val)+1));
#endif
return io;
}
Setzt die Cursorposition auf column in der gleichen Zeile der aktuellen Position.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_iflush(VALUE io)
{
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
int fd = GetReadFD(io);
if (tcflush(fd, TCIFLUSH)) sys_fail(io);
#endif
return io;
}
Leert den Eingabepuffer im Kernel.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
rb_io_inspect(VALUE obj)
{
rb_io_t *fptr;
VALUE result;
static const char closed[] = " (closed)";
fptr = RFILE(obj)->fptr;
if (!fptr) return rb_any_to_s(obj);
result = rb_str_new_cstr("#<");
rb_str_append(result, rb_class_name(CLASS_OF(obj)));
rb_str_cat2(result, ":");
if (NIL_P(fptr->pathv)) {
if (fptr->fd < 0) {
rb_str_cat(result, closed+1, strlen(closed)-1);
}
else {
rb_str_catf(result, "fd %d", fptr->fd);
}
}
else {
rb_str_append(result, fptr->pathv);
if (fptr->fd < 0) {
rb_str_cat(result, closed, strlen(closed));
}
}
return rb_str_cat2(result, ">");
}
Gibt eine String-Repräsentation von self zurück.
f = File.open('t.txt') f.inspect # => "#<File:t.txt>" f.close
Source
static VALUE
rb_io_internal_encoding(VALUE io)
{
rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
if (!fptr->encs.enc2) return Qnil;
return rb_enc_from_encoding(io_read_encoding(fptr));
}
Source
static VALUE
rb_io_ioctl(int argc, VALUE *argv, VALUE io)
{
VALUE req, arg;
rb_scan_args(argc, argv, "11", &req, &arg);
return rb_ioctl(io, req, arg);
}
Ruft den Posix-Systemaufruf ioctl(2) auf, der einen Low-Level-Befehl an ein E/A-Gerät ausgibt.
Gibt einen Low-Level-Befehl an ein E/A-Gerät aus. Die Argumente und der Rückgabewert sind plattformabhängig. Die Auswirkung des Aufrufs ist plattformabhängig.
Wenn argument ein Integer ist, wird es direkt übergeben; wenn es eine Zeichenkette ist, wird es als binäre Bytefolge interpretiert.
Nicht auf allen Plattformen implementiert.
Source
static VALUE
console_ioflush(VALUE io)
{
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
int fd1 = GetReadFD(io);
int fd2 = GetWriteFD(io);
if (fd2 != -1 && fd1 != fd2) {
if (tcflush(fd1, TCIFLUSH)) sys_fail(io);
if (tcflush(fd2, TCOFLUSH)) sys_fail(io);
}
else {
if (tcflush(fd1, TCIOFLUSH)) sys_fail(io);
}
#endif
return io;
}
Leert die Eingabe- und Ausgabepuffer im Kernel.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
rb_io_isatty(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
return RBOOL(isatty(fptr->fd) != 0);
}
Gibt true zurück, wenn der Stream mit einem Terminalgerät (tty) verbunden ist, andernfalls false.
f = File.new('t.txt').isatty #=> false f.close f = File.new('/dev/tty').isatty #=> true f.close
Source
static VALUE
rb_io_lineno(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
return INT2NUM(fptr->lineno);
}
Gibt die aktuelle Zeilennummer für den Stream zurück; siehe Zeilennummer.
Source
static VALUE
rb_io_set_lineno(VALUE io, VALUE lineno)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
fptr->lineno = NUM2INT(lineno);
return lineno;
}
Setzt und gibt die Zeilennummer für den Stream zurück; siehe Zeilennummer.
Source
static VALUE
console_noecho(VALUE io)
{
return ttymode(io, rb_yield, io, set_noecho, NULL);
}
Gibt self mit deaktivierter Echo-Ausgabe zurück.
STDIN.noecho(&:gets)
Liest und gibt eine Zeile ohne Echo zurück.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
rb_io_nonblock_block(int argc, VALUE *argv, VALUE self)
{
int nb = 1;
int descriptor = rb_io_descriptor(self);
if (argc > 0) {
VALUE v;
rb_scan_args(argc, argv, "01", &v);
nb = RTEST(v);
}
int current_flags = get_fcntl_flags(descriptor);
int restore[2] = {descriptor, current_flags};
if (!io_nonblock_set(descriptor, current_flags, nb))
return rb_yield(self);
return rb_ensure(rb_yield, self, io_nonblock_restore, (VALUE)restore);
}
Gibt self im nicht-blockierenden Modus zurück.
Wenn false als Argument übergeben wird, wird self im blockierenden Modus zurückgegeben. Der ursprüngliche Modus wird nach Ausführung des Blocks wiederhergestellt.
Source
static VALUE
rb_io_nonblock_set(VALUE self, VALUE value)
{
if (RTEST(value)) {
rb_io_t *fptr;
GetOpenFile(self, fptr);
rb_io_set_nonblock(fptr);
}
else {
int descriptor = rb_io_descriptor(self);
io_nonblock_set(descriptor, get_fcntl_flags(descriptor), RTEST(value));
}
return self;
}
Aktiviert den nicht-blockierenden Modus für einen Stream, wenn er auf true gesetzt ist, und den blockierenden Modus, wenn er auf false gesetzt ist.
Diese Methode setzt oder löscht das O_NONBLOCK-Flag für den Dateideskriptor in ios.
Das Verhalten der meisten IO-Methoden wird von diesem Flag nicht beeinflusst, da sie Systemaufrufe wiederholen, um ihre Aufgabe nach EAGAIN und teilweisem Lesen/Schreiben abzuschließen. (Eine Ausnahme bildet IO#syswrite, das nicht wiederholt wird.)
Diese Methode kann verwendet werden, um den nicht-blockierenden Modus von Standard-E/A zu löschen. Da nicht-blockierende Methoden (read_nonblock usw.) den nicht-blockierenden Modus setzen, ihn aber nicht löschen, ist diese Methode wie folgt verwendbar.
END { STDOUT.nonblock = false } STDOUT.write_nonblock("foo")
Da das Flag über Prozesse hinweg geteilt wird und viele Nicht-Ruby-Befehle keine Standard-E/A mit nicht-blockierendem Modus erwarten, ist es sicher, das Flag zu löschen, bevor das Ruby-Programm beendet wird.
Zum Beispiel lässt das folgende Ruby-Programm STDIN/STDOUT/STDER im nicht-blockierenden Modus. (STDIN, STDOUT und STDERR sind mit einem Terminal verbunden. Das Setzen eines davon auf nicht-blockierend wirkt sich auf die anderen beiden aus.) So versucht der cat-Befehl, von der Standardeingabe zu lesen, und verursacht einen Fehler "Resource temporarily unavailable" (EAGAIN).
% ruby -e '
STDOUT.write_nonblock("foo\n")'; cat
foo
cat: -: Resource temporarily unavailable
Das Löschen des Flags lässt das Verhalten des cat-Befehls normal erscheinen. (Der cat-Befehl wartet auf Eingaben von der Standardeingabe.)
% ruby -rio/nonblock -e '
END { STDOUT.nonblock = false }
STDOUT.write_nonblock("foo")
'; cat
foo
Source
static VALUE
rb_io_nonblock_p(VALUE io)
{
if (get_fcntl_flags(rb_io_descriptor(io)) & O_NONBLOCK)
return Qtrue;
return Qfalse;
}
Gibt true zurück, wenn ein IO-Objekt im nicht-blockierenden Modus ist.
Source
static VALUE
console_oflush(VALUE io)
{
int fd = GetWriteFD(io);
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
if (tcflush(fd, TCOFLUSH)) sys_fail(io);
#endif
(void)fd;
return io;
}
Leert den Ausgabepuffer im Kernel.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
VALUE
rb_io_path(VALUE io)
{
rb_io_t *fptr = RFILE(io)->fptr;
if (!fptr)
return Qnil;
return rb_obj_dup(fptr->pathv);
}
Gibt den mit dem IO verbundenen Pfad zurück oder nil, wenn kein Pfad mit dem IO verbunden ist. Es ist nicht garantiert, dass der Pfad im Dateisystem existiert.
$stdin.path # => "<STDIN>" File.open("testfile") {|f| f.path} # => "testfile"
Source
static VALUE
io_pathconf(VALUE io, VALUE arg)
{
int name;
long ret;
name = NUM2INT(arg);
errno = 0;
ret = fpathconf(rb_io_descriptor(io), name);
if (ret == -1) {
if (errno == 0) /* no limit */
return Qnil;
rb_sys_fail("fpathconf");
}
return LONG2NUM(ret);
}
Gibt die Pfadnamen-Konfigurationsvariable mittels fpathconf() zurück.
name sollte eine Konstante unter Etc sein, die mit PC_ beginnt.
Der Rückgabewert ist ein Integer oder nil. nil bedeutet unendliches Limit. (fpathconf() gibt -1 zurück, aber errno wird nicht gesetzt.)
require 'etc' IO.pipe {|r, w| p w.pathconf(Etc::PC_PIPE_BUF) #=> 4096 }
Source
static VALUE
rb_io_pid(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
if (!fptr->pid)
return Qnil;
return PIDT2NUM(fptr->pid);
}
Gibt die Prozess-ID eines mit dem Stream verbundenen Kindprozesses zurück, die von IO#popen gesetzt wurde, oder nil, wenn der Stream nicht von IO#popen erstellt wurde.
pipe = IO.popen("-") if pipe $stderr.puts "In parent, child pid is #{pipe.pid}" else $stderr.puts "In child, pid is #{$$}" end
Ausgabe
In child, pid is 26209 In parent, child pid is 26209
Source
static VALUE
rb_io_set_pos(VALUE io, VALUE offset)
{
rb_io_t *fptr;
rb_off_t pos;
pos = NUM2OFFT(offset);
GetOpenFile(io, fptr);
pos = io_seek(fptr, pos, SEEK_SET);
if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
return OFFT2NUM(pos);
}
Source
static VALUE
rb_io_pread(int argc, VALUE *argv, VALUE io)
{
VALUE len, offset, str;
rb_io_t *fptr;
ssize_t n;
struct prdwr_internal_arg arg;
int shrinkable;
rb_scan_args(argc, argv, "21", &len, &offset, &str);
arg.count = NUM2SIZET(len);
arg.offset = NUM2OFFT(offset);
shrinkable = io_setstrbuf(&str, (long)arg.count);
if (arg.count == 0) return str;
arg.buf = RSTRING_PTR(str);
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
arg.io = fptr;
arg.fd = fptr->fd;
rb_io_check_closed(fptr);
rb_str_locktmp(str);
n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
if (n < 0) {
rb_sys_fail_path(fptr->pathv);
}
io_set_read_length(str, n, shrinkable);
if (n == 0 && arg.count > 0) {
rb_eof_error();
}
return str;
}
Verhält sich wie IO#readpartial, außer dass es
-
an der angegebenen
offset(in Bytes) liest. -
ignoriert die Position des Streams (siehe Position) und verändert sie nicht.
-
umgeht jegliche Benutzer-Speicherpufferung im Stream.
Da diese Methode den Zustand des Streams (insbesondere seine Position) nicht stört, ermöglicht pread mehreren Threads und Prozessen die Verwendung desselben IO-Objekts zum Lesen an verschiedenen Offsets.
f = File.open('t.txt') f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.pos # => 52 # Read 12 bytes at offset 0. f.pread(12, 0) # => "First line\n" # Read 9 bytes at offset 8. f.pread(9, 8) # => "ne\nSecon" f.close
Auf einigen Plattformen nicht verfügbar.
Source
static VALUE
console_key_pressed_p(VALUE io, VALUE k)
{
int vk = -1;
if (FIXNUM_P(k)) {
vk = NUM2UINT(k);
}
else {
const struct vktable *t;
const char *kn;
if (SYMBOL_P(k)) {
k = rb_sym2str(k);
kn = RSTRING_PTR(k);
}
else {
kn = StringValuePtr(k);
}
t = console_win32_vk(kn, RSTRING_LEN(k));
if (!t || (vk = (short)t->vk) == -1) {
rb_raise(rb_eArgError, "unknown virtual key code: % "PRIsVALUE, k);
}
}
return GetKeyState(vk) & 0x80 ? Qtrue : Qfalse;
}
Source
VALUE
rb_io_print(int argc, const VALUE *argv, VALUE out)
{
int i;
VALUE line;
/* if no argument given, print `$_' */
if (argc == 0) {
argc = 1;
line = rb_lastline_get();
argv = &line;
}
if (argc > 1 && !NIL_P(rb_output_fs)) {
rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
}
for (i=0; i<argc; i++) {
if (!NIL_P(rb_output_fs) && i>0) {
rb_io_write(out, rb_output_fs);
}
rb_io_write(out, argv[i]);
}
if (argc > 0 && !NIL_P(rb_output_rs)) {
rb_io_write(out, rb_output_rs);
}
return Qnil;
}
Schreibt die gegebenen Objekte in den Stream; gibt nil zurück. Hängt den Ausgabedatensatztrenner $OUTPUT_RECORD_SEPARATOR ($\) an, wenn dieser nicht nil ist. Siehe Zeilen-E/A.
Mit dem Argument objects, für jedes Objekt
-
Konvertiert über seine Methode
to_s, wenn es keine Zeichenkette ist. -
Schreibt in den Stream.
-
Wenn es nicht das letzte Objekt ist, schreibt es den Ausgabefeldtrenner
$OUTPUT_FIELD_SEPARATOR($,), wenn dieser nichtnilist.
Mit Standardtrennzeichen
f = File.open('t.tmp', 'w+') objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero'] p $OUTPUT_RECORD_SEPARATOR p $OUTPUT_FIELD_SEPARATOR f.print(*objects) f.rewind p f.read f.close
Ausgabe
nil nil "00.00/10+0izerozero"
Mit spezifizierten Trennzeichen
$\ = "\n" $, = ',' f.rewind f.print(*objects) f.rewind p f.read
Ausgabe
"0,0.0,0/1,0+0i,zero,zero\n"
Ohne Argument wird der Inhalt von $_ geschrieben (was normalerweise die letzte Benutzereingabe ist).
f = File.open('t.tmp', 'w+') gets # Sets $_ to the most recent user input. f.print f.close
Source
VALUE
rb_io_printf(int argc, const VALUE *argv, VALUE out)
{
rb_io_write(out, rb_f_sprintf(argc, argv));
return Qnil;
}
Formatiert und schreibt objects in den Stream.
Details zu format_string finden Sie unter Formatangaben.
Source
static VALUE
rb_io_putc(VALUE io, VALUE ch)
{
VALUE str;
if (RB_TYPE_P(ch, T_STRING)) {
str = rb_str_substr(ch, 0, 1);
}
else {
char c = NUM2CHR(ch);
str = rb_str_new(&c, 1);
}
rb_io_write(io, str);
return ch;
}
Schreibt ein Zeichen in den Stream. Siehe Zeichen-E/A.
Wenn object numerisch ist, wird es bei Bedarf in einen Integer konvertiert, dann wird das Zeichen mit dem Code als niederwertigstes Byte geschrieben; wenn object eine Zeichenkette ist, wird das erste Zeichen geschrieben.
$stdout.putc "A" $stdout.putc 65
Ausgabe
AA
Source
VALUE
rb_io_puts(int argc, const VALUE *argv, VALUE out)
{
VALUE line, args[2];
/* if no argument given, print newline. */
if (argc == 0) {
rb_io_write(out, rb_default_rs);
return Qnil;
}
for (int i = 0; i < argc; i++) {
// Convert the argument to a string:
if (RB_TYPE_P(argv[i], T_STRING)) {
line = argv[i];
}
else if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
continue;
}
else {
line = rb_obj_as_string(argv[i]);
}
// Write the line:
int n = 0;
if (RSTRING_LEN(line) == 0) {
args[n++] = rb_default_rs;
}
else {
args[n++] = line;
if (!rb_str_end_with_asciichar(line, '\n')) {
args[n++] = rb_default_rs;
}
}
rb_io_writev(out, n, args);
}
return Qnil;
}
Schreibt die gegebenen objects in den Stream, der zum Schreiben geöffnet sein muss (siehe Zugriffsmodi); gibt nil zurück. Schreibt eine neue Zeile nach jedem, der nicht bereits mit einer Zeilentrennsequenz endet. Wenn ohne Argumente aufgerufen, schreibt eine neue Zeile. Siehe Zeilen-E/A.
Beachten Sie, dass jede hinzugefügte neue Zeile das Zeichen "\n" ist, nicht der Ausgabedatensatztrenner ($\).
Behandlung für jedes Objekt
-
String: schreibt den String.
-
Weder String noch Array: schreibt
object.to_s. -
Array: schreibt jedes Element des Arrays; Arrays können verschachtelt sein.
Um diese Beispiele kurz zu halten, definieren wir diese Hilfsmethode
def show(*objects) # Puts objects to file. f = File.new('t.tmp', 'w+') f.puts(objects) # Return file content. f.rewind p f.read f.close end # Strings without newlines. show('foo', 'bar', 'baz') # => "foo\nbar\nbaz\n" # Strings, some with newlines. show("foo\n", 'bar', "baz\n") # => "foo\nbar\nbaz\n" # Neither strings nor arrays: show(0, 0.0, Rational(0, 1), Complex(9, 0), :zero) # => "0\n0.0\n0/1\n9+0i\nzero\n" # Array of strings. show(['foo', "bar\n", 'baz']) # => "foo\nbar\nbaz\n" # Nested arrays. show([[[0, 1], 2, 3], 4, 5]) # => "0\n1\n2\n3\n4\n5\n"
Source
static VALUE
rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
{
rb_io_t *fptr;
ssize_t n;
struct prdwr_internal_arg arg;
VALUE tmp;
if (!RB_TYPE_P(str, T_STRING))
str = rb_obj_as_string(str);
arg.offset = NUM2OFFT(offset);
io = GetWriteIO(io);
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
arg.io = fptr;
arg.fd = fptr->fd;
tmp = rb_str_tmp_frozen_acquire(str);
arg.buf = RSTRING_PTR(tmp);
arg.count = (size_t)RSTRING_LEN(tmp);
n = (ssize_t)pwrite_internal_call((VALUE)&arg);
if (n < 0) rb_sys_fail_path(fptr->pathv);
rb_str_tmp_frozen_release(str, tmp);
return SSIZET2NUM(n);
}
Verhält sich wie IO#write, außer dass es
-
an der angegebenen
offset(in Bytes) schreibt. -
ignoriert die Position des Streams (siehe Position) und verändert sie nicht.
-
umgeht jegliche Benutzer-Speicherpufferung im Stream.
Da diese Methode den Zustand des Streams (insbesondere seine Position) nicht stört, ermöglicht pwrite mehreren Threads und Prozessen die Verwendung desselben IO-Objekts zum Schreiben an verschiedenen Offsets.
f = File.open('t.tmp', 'w+') # Write 6 bytes at offset 3. f.pwrite('ABCDEF', 3) # => 6 f.rewind f.read # => "\u0000\u0000\u0000ABCDEF" f.close
Auf einigen Plattformen nicht verfügbar.
Source
static VALUE
console_raw(int argc, VALUE *argv, VALUE io)
{
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
return ttymode(io, rb_yield, io, set_rawmode, optp);
}
Gibt self im Rohmodus zurück und gibt das Ergebnis des Blocks zurück.
STDIN.raw(&:gets)
Liest und gibt eine Zeile ohne Echo und Zeilenbearbeitung zurück.
Der Parameter min gibt die Mindestanzahl von Bytes an, die bei einem Leseaufruf empfangen werden sollen. (Standard: 1)
Der Parameter time gibt das Timeout in Sekunden mit einer Präzision von 1/10 Sekunde an. (Standard: 0)
Wenn der Parameter intr true ist, werden die Sonderzeichen für Unterbrechung, Abbruch, Beendigung und Suspendierung aktiviert.
Weitere Einzelheiten finden Sie auf der Manpage von termios.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_set_raw(int argc, VALUE *argv, VALUE io)
{
conmode t;
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
int fd = GetReadFD(io);
if (!getattr(fd, &t)) sys_fail(io);
set_rawmode(&t, optp);
if (!setattr(fd, &t)) sys_fail(io);
return io;
}
Aktiviert den Rohmodus und gibt io zurück.
Wenn der Terminalmodus wiederhergestellt werden muss, verwenden Sie io.raw { ... }.
Siehe IO#raw für Details zu den Parametern.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
io_read(int argc, VALUE *argv, VALUE io)
{
rb_io_t *fptr;
long n, len;
VALUE length, str;
int shrinkable;
#if RUBY_CRLF_ENVIRONMENT
int previous_mode;
#endif
rb_scan_args(argc, argv, "02", &length, &str);
if (NIL_P(length)) {
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
return read_all(fptr, remain_size(fptr), str);
}
len = NUM2LONG(length);
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
shrinkable = io_setstrbuf(&str,len);
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
if (len == 0) {
io_set_read_length(str, 0, shrinkable);
return str;
}
READ_CHECK(fptr);
#if RUBY_CRLF_ENVIRONMENT
previous_mode = set_binary_mode_with_seek_cur(fptr);
#endif
n = io_fread(str, 0, len, fptr);
io_set_read_length(str, n, shrinkable);
#if RUBY_CRLF_ENVIRONMENT
if (previous_mode == O_TEXT) {
setmode(fptr->fd, O_TEXT);
}
#endif
if (n == 0) return Qnil;
return str;
}
Liest Bytes aus dem Stream; der Stream muss zum Lesen geöffnet sein (siehe Zugriffsmodi).
-
Wenn
maxlennilist, werden alle Bytes im Datentyp des Streams gelesen. -
Andernfalls werden bis zu
maxlenBytes im Binärmodus gelesen.
Gibt eine Zeichenkette zurück (entweder eine neue Zeichenkette oder die gegebene out_string) mit den gelesenen Bytes. Die Kodierung der Zeichenkette hängt sowohl von maxLen als auch von out_string ab.
-
maxlenistnil: verwendet die interne Kodierung vonself(unabhängig davon, obout_stringangegeben wurde). -
maxlennichtnil-
out_stringgegeben: Kodierung vonout_stringunverändert. -
out_stringnicht gegeben: ASCII-8BIT wird verwendet.
-
Ohne Argument out_string
Wenn das Argument out_string weggelassen wird, ist der Rückgabewert eine neue Zeichenkette.
f = File.new('t.txt') f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.rewind f.read(30) # => "First line\r\nSecond line\r\n\r\nFou" f.read(30) # => "rth line\r\nFifth line\r\n" f.read(30) # => nil f.close
Wenn maxlen null ist, wird eine leere Zeichenkette zurückgegeben.
Mit Argument out_string
Wenn das Argument out_string gegeben ist, ist der Rückgabewert out_string, dessen Inhalt ersetzt wird.
f = File.new('t.txt') s = 'foo' # => "foo" f.read(nil, s) # => "First line\nSecond line\n\nFourth line\nFifth line\n" s # => "First line\nSecond line\n\nFourth line\nFifth line\n" f.rewind s = 'bar' f.read(30, s) # => "First line\r\nSecond line\r\n\r\nFou" s # => "First line\r\nSecond line\r\n\r\nFou" s = 'baz' f.read(30, s) # => "rth line\r\nFifth line\r\n" s # => "rth line\r\nFifth line\r\n" s = 'bat' f.read(30, s) # => nil s # => "" f.close
Beachten Sie, dass diese Methode der Funktion fread() in C ähnelt. Das bedeutet, dass sie wiederholt read(2) Systemaufrufe aufruft, um Daten mit der angegebenen maxlen (oder bis EOF) zu lesen.
Dieses Verhalten bleibt erhalten, auch wenn der Stream im nicht-blockierenden Modus ist. (Diese Methode ist unempfindlich gegenüber dem nicht-blockierenden Flag, wie andere Methoden auch.)
Wenn Sie das Verhalten eines einzelnen read(2) Systemaufrufs benötigen, sollten Sie readpartial, read_nonblock und sysread in Betracht ziehen.
Verwandt: IO#write.
Source
# File io.rb, line 62 def read_nonblock(len, buf = nil, exception: true) Primitive.io_read_nonblock(len, buf, exception) end
Liest höchstens maxlen Bytes aus ios unter Verwendung des read(2) Systemaufrufs, nachdem O_NONBLOCK für den zugrunde liegenden Dateideskriptor gesetzt wurde.
Wenn das optionale Argument outbuf vorhanden ist, muss es auf einen String verweisen, der die Daten empfängt. outbuf enthält nach dem Methodenaufruf nur die empfangenen Daten, auch wenn er anfänglich nicht leer war.
read_nonblock ruft lediglich den read(2) Systemaufruf auf. Dies verursacht alle Fehler, die der read(2) Systemaufruf verursacht: Errno::EWOULDBLOCK, Errno::EINTR usw. Der Aufrufer sollte sich um solche Fehler kümmern.
Wenn die Ausnahme Errno::EWOULDBLOCK oder Errno::EAGAIN ist, wird sie von IO::WaitReadable erweitert. Daher kann IO::WaitReadable verwendet werden, um die Ausnahmen für die Wiederholung von read_nonblock abzufangen.
read_nonblock verursacht bei EOF einen EOFError.
Auf einigen Plattformen, wie z. B. Windows, wird der nicht-blockierende Modus für IO-Objekte, die keine Sockets sind, nicht unterstützt. In solchen Fällen wird Errno::EBADF ausgelöst.
Wenn der Lese-Bytepuffer nicht leer ist, liest read_nonblock aus dem Puffer wie readpartial. In diesem Fall wird der read(2) Systemaufruf nicht aufgerufen.
Wenn read_nonblock eine Ausnahme vom Typ IO::WaitReadable auslöst, sollte read_nonblock erst aufgerufen werden, wenn io lesbar ist, um eine Endlosschleife zu vermeiden. Dies kann wie folgt geschehen.
# emulates blocking read (readpartial). begin result = io.read_nonblock(maxlen) rescue IO::WaitReadable IO.select([io]) retry end
Obwohl IO#read_nonblock keine IO::WaitWritable auslöst. OpenSSL::Buffering#read_nonblock kann IO::WaitWritable auslösen. Wenn IO und SSL polymorph verwendet werden sollen, sollte auch IO::WaitWritable abgefangen werden. Siehe das Dokument von OpenSSL::Buffering#read_nonblock für Beispielcode.
Beachten Sie, dass diese Methode mit readpartial identisch ist, mit dem Unterschied, dass das nicht-blockierende Flag gesetzt ist.
Durch Angabe des Schlüsselwortarguments exception auf false können Sie angeben, dass read_nonblock keine IO::WaitReadable Ausnahme auslösen, sondern das Symbol :wait_readable zurückgeben soll. Bei EOF gibt es nil zurück, anstatt EOFError auszulösen.
Source
static VALUE
rb_io_readbyte(VALUE io)
{
VALUE c = rb_io_getbyte(io);
if (NIL_P(c)) {
rb_eof_error();
}
return c;
}
Liest und gibt das nächste Byte (im Bereich 0..255) aus dem Stream zurück; löst EOFError aus, wenn bereits am Ende des Streams. Siehe Byte-E/A.
f = File.open('t.txt') f.readbyte # => 70 f.close f = File.open('t.rus') f.readbyte # => 209 f.close
Verwandt: IO#getbyte (löst keine EOFError aus).
Source
static VALUE
rb_io_readchar(VALUE io)
{
VALUE c = rb_io_getc(io);
if (NIL_P(c)) {
rb_eof_error();
}
return c;
}
Liest und gibt den nächsten 1-Zeichen-String aus dem Stream zurück; löst EOFError aus, wenn bereits am Ende des Streams. Siehe Zeichen-E/A.
f = File.open('t.txt') f.readchar # => "F" f.close f = File.open('t.rus') f.readchar.ord # => 1090 f.close
Source
# File io.rb, line 133 def readline(sep = $/, limit = nil, chomp: false) Primitive.io_readline(sep, limit, chomp) end
Source
static VALUE
rb_io_readlines(int argc, VALUE *argv, VALUE io)
{
struct getline_arg args;
prepare_getline_args(argc, argv, &args, io);
return io_readlines(&args, io);
}
Liest und gibt alle verbleibenden Zeilen aus dem Stream zurück; ändert $_ nicht. Siehe Zeilen-E/A.
Ohne Argumente zurück, werden Zeilen zurückgegeben, wie sie durch den Zeilentrenner $/ bestimmt werden, oder nil, wenn keine vorhanden sind.
f = File.new('t.txt') f.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"] f.readlines # => [] f.close
Nur mit dem String-Argument sep gegeben, werden Zeilen zurückgegeben, wie sie durch den Zeilentrenner sep bestimmt werden, oder nil, wenn keine vorhanden sind; siehe Zeilentrenner.
f = File.new('t.txt') f.readlines('li') # => ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"] f.close
Die beiden Sonderwerte für sep werden berücksichtigt.
f = File.new('t.txt') # Get all into one string. f.readlines(nil) # => ["First line\nSecond line\n\nFourth line\nFifth line\n"] # Get paragraphs (up to two line separators). f.rewind f.readlines('') # => ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"] f.close
Wenn nur das Integer-Argument limit gegeben ist, wird die Anzahl der Bytes pro Zeile begrenzt; siehe Zeilenlimit.
f = File.new('t.txt') f.readlines(8) # => ["First li", "ne\n", "Second l", "ine\n", "\n", "Fourth l", "ine\n", "Fifth li", "ne\n"] f.close
Mit den Argumenten sep und limit werden die beiden Verhaltensweisen kombiniert (siehe Zeilentrenner und Zeilenlimit).
Das optionale Schlüsselwortargument chomp gibt an, ob Zeilentrenner weggelassen werden sollen.
f = File.new('t.txt') f.readlines(chomp: true) # => ["First line", "Second line", "", "Fourth line", "Fifth line"] f.close
Source
static VALUE
io_readpartial(int argc, VALUE *argv, VALUE io)
{
VALUE ret;
ret = io_getpartial(argc, argv, io, Qnil, 0);
if (NIL_P(ret))
rb_eof_error();
return ret;
}
Liest bis zu maxlen Bytes aus dem Stream; gibt eine Zeichenkette zurück (entweder eine neue Zeichenkette oder die gegebene out_string). Ihre Kodierung ist
-
Die unveränderte Kodierung von
out_string, wennout_stringgegeben ist. -
ASCII-8BIT, andernfalls.
-
Enthält
maxlenBytes aus dem Stream, falls verfügbar. -
Andernfalls enthält alle verfügbaren Bytes, falls welche verfügbar sind.
-
Andernfalls ist es eine leere Zeichenkette.
Mit dem einzigen nicht-negativen Integer-Argument maxlen gegeben, gibt eine neue Zeichenkette zurück.
f = File.new('t.txt') f.readpartial(20) # => "First line\nSecond l" f.readpartial(20) # => "ine\n\nFourth line\n" f.readpartial(20) # => "Fifth line\n" f.readpartial(20) # Raises EOFError. f.close
Mit beiden Argumenten maxlen und dem String-Argument out_string gegeben, gibt die modifizierte out_string zurück.
f = File.new('t.txt') s = 'foo' f.readpartial(20, s) # => "First line\nSecond l" s = 'bar' f.readpartial(0, s) # => "" f.close
Diese Methode ist nützlich für Streams wie Pipes, Sockets oder TTYs. Sie blockiert nur, wenn keine Daten sofort verfügbar sind. Das bedeutet, dass sie nur blockiert, wenn *alle* der folgenden Bedingungen erfüllt sind:
-
Der Bytepuffer im Stream ist leer.
-
Der Inhalt des Streams ist leer.
-
Der Stream ist nicht am EOF.
Wenn blockiert, wartet die Methode auf entweder mehr Daten oder EOF auf dem Stream.
-
Wenn mehr Daten gelesen werden, gibt die Methode die Daten zurück.
-
Wenn EOF erreicht ist, löst die Methode
EOFErroraus.
Wenn nicht blockiert, reagiert die Methode sofort.
-
Gibt Daten aus dem Puffer zurück, wenn welche vorhanden sind.
-
Andernfalls werden Daten aus dem Stream zurückgegeben, wenn welche vorhanden sind.
-
Andernfalls wird
EOFErrorausgelöst, wenn der Stream EOF erreicht hat.
Beachten Sie, dass diese Methode sysread ähnelt. Die Unterschiede sind:
-
Wenn der Bytepuffer nicht leer ist, wird aus dem Bytepuffer gelesen, anstatt "sysread für gepufferte
IO(IOError)". -
Es löst keine Errno::EWOULDBLOCK und Errno::EINTR aus. Wenn readpartial EWOULDBLOCK und EINTR durch den Leseaufruf feststellt, wiederholt readpartial den Systemaufruf.
Letzteres bedeutet, dass readpartial unempfindlich gegenüber dem nicht-blockierenden Flag ist. Es blockiert in der Situation, in der IO#sysread Errno::EWOULDBLOCK verursacht, als ob der FD im blockierenden Modus wäre.
Beispiele
# # Returned Buffer Content Pipe Content r, w = IO.pipe # w << 'abc' # "" "abc". r.readpartial(4096) # => "abc" "" "" r.readpartial(4096) # (Blocks because buffer and pipe are empty.) # # Returned Buffer Content Pipe Content r, w = IO.pipe # w << 'abc' # "" "abc" w.close # "" "abc" EOF r.readpartial(4096) # => "abc" "" EOF r.readpartial(4096) # raises EOFError # # Returned Buffer Content Pipe Content r, w = IO.pipe # w << "abc\ndef\n" # "" "abc\ndef\n" r.gets # => "abc\n" "def\n" "" w << "ghi\n" # "def\n" "ghi\n" r.readpartial(4096) # => "def\n" "" "ghi\n" r.readpartial(4096) # => "ghi\n" "" ""
Source
static VALUE
rb_io_reopen(int argc, VALUE *argv, VALUE file)
{
VALUE fname, nmode, opt;
int oflags;
rb_io_t *fptr;
if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
VALUE tmp = rb_io_check_io(fname);
if (!NIL_P(tmp)) {
return io_reopen(file, tmp);
}
}
FilePathValue(fname);
rb_io_taint_check(file);
fptr = RFILE(file)->fptr;
if (!fptr) {
fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
}
if (!NIL_P(nmode) || !NIL_P(opt)) {
enum rb_io_mode fmode;
struct rb_io_encoding convconfig;
rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
if (RUBY_IO_EXTERNAL_P(fptr) &&
((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
(fptr->mode & FMODE_READWRITE)) {
rb_raise(rb_eArgError,
"%s can't change access mode from \"%s\" to \"%s\"",
PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
rb_io_fmode_modestr(fmode));
}
fptr->mode = fmode;
fptr->encs = convconfig;
}
else {
oflags = rb_io_fmode_oflags(fptr->mode);
}
fptr->pathv = fname;
if (fptr->fd < 0) {
fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
fptr->stdio_file = 0;
return file;
}
if (fptr->mode & FMODE_WRITABLE) {
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
}
fptr->rbuf.off = fptr->rbuf.len = 0;
if (fptr->stdio_file) {
int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
rb_io_oflags_modestr(oflags),
fptr->stdio_file);
if (e) rb_syserr_fail_path(e, fptr->pathv);
fptr->fd = fileno(fptr->stdio_file);
rb_fd_fix_cloexec(fptr->fd);
#ifdef USE_SETVBUF
if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
#endif
if (fptr->stdio_file == stderr) {
if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
}
else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
}
}
else {
int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
int err = 0;
if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
err = errno;
(void)close(tmpfd);
if (err) {
rb_syserr_fail_path(err, fptr->pathv);
}
}
return file;
}
Ordnet den Stream einem anderen Stream neu zu, der auch einer anderen Klasse angehören kann. Diese Methode kann verwendet werden, um einen bestehenden Stream auf ein neues Ziel umzuleiten.
Mit dem Argument other_io gegeben, ordnet es sich dem Stream neu zu.
# Redirect $stdin from a file. f = File.open('t.txt') $stdin.reopen(f) f.close # Redirect $stdout to a file. f = File.open('t.tmp', 'w') $stdout.reopen(f) f.close
Mit dem Argument path gegeben, ordnet es sich einem neuen Stream zu diesem Dateipfad neu zu.
$stdin.reopen('t.txt') $stdout.reopen('t.tmp', 'w')
Optionale Schlüsselwortargumente opts spezifizieren
Source
static VALUE
rb_io_rewind(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
if (io == ARGF.current_file) {
ARGF.lineno -= fptr->lineno;
}
fptr->lineno = 0;
if (fptr->readconv) {
clear_readconv(fptr);
}
return INT2FIX(0);
}
Positioniert den Stream zurück an den Anfang, wobei sowohl die Position als auch die Zeilennummer auf Null gesetzt werden; siehe Position und Zeilennummer.
f = File.open('t.txt') f.tell # => 0 f.lineno # => 0 f.gets # => "First line\n" f.tell # => 12 f.lineno # => 1 f.rewind # => 0 f.tell # => 0 f.lineno # => 0 f.close
Beachten Sie, dass diese Methode nicht mit Streams wie Pipes, TTYs und Sockets verwendet werden kann.
Source
static VALUE
console_scroll_backward(VALUE io, VALUE val)
{
return console_scroll(io, -NUM2INT(val));
}
Scrollt die gesamte Anzeige um n Zeilen nach hinten.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_scroll_forward(VALUE io, VALUE val)
{
return console_scroll(io, +NUM2INT(val));
}
Scrollt die gesamte Anzeige um n Zeilen nach vorne.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
rb_io_seek_m(int argc, VALUE *argv, VALUE io)
{
VALUE offset, ptrname;
int whence = SEEK_SET;
if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
whence = interpret_seek_whence(ptrname);
}
return rb_io_seek(io, offset, whence);
}
Setzt die Position auf den durch den Integer offset angegebenen Wert (siehe Position) und die Konstante whence, die eine der folgenden ist:
-
:CURoderIO::SEEK_CUR: Positioniert den Stream von seiner aktuellen Position plus dem gegebenenoffsetneu.f = File.open('t.txt') f.tell # => 0 f.seek(20, :CUR) # => 0 f.tell # => 20 f.seek(-10, :CUR) # => 0 f.tell # => 10 f.close
-
:ENDoderIO::SEEK_END: Positioniert den Stream von seinem Ende plus dem gegebenenoffsetneu.f = File.open('t.txt') f.tell # => 0 f.seek(0, :END) # => 0 # Repositions to stream end. f.tell # => 52 f.seek(-20, :END) # => 0 f.tell # => 32 f.seek(-40, :END) # => 0 f.tell # => 12 f.close
-
:SEToderIO:SEEK_SET: Positioniert den Stream auf den gegebenenoffsetneu.f = File.open('t.txt') f.tell # => 0 f.seek(20, :SET) # => 0 f.tell # => 20 f.seek(40, :SET) # => 0 f.tell # => 40 f.close
Source
static VALUE
rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
{
rb_io_t *fptr;
VALUE v1, v2, opt;
if (!RB_TYPE_P(io, T_FILE)) {
return forward(io, id_set_encoding, argc, argv);
}
argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
GetOpenFile(io, fptr);
io_encoding_set(fptr, v1, v2, opt);
return io;
}
Siehe Encodings.
Das Argument ext_enc muss, wenn es gegeben ist, ein Encoding-Objekt oder eine String mit dem Kodierungsnamen sein; es wird als Kodierung für den Stream zugewiesen.
Das Argument int_enc muss, wenn es gegeben ist, ein Encoding-Objekt oder eine String mit dem Kodierungsnamen sein; es wird als Kodierung für die interne Zeichenkette zugewiesen.
Das Argument 'ext_enc:int_enc', wenn es gegeben ist, ist eine Zeichenkette, die zwei durch Doppelpunkte getrennte Kodierungsnamen enthält; die entsprechenden Encoding-Objekte werden als externe und interne Kodierungen für den Stream zugewiesen.
Wenn die externe Kodierung einer Zeichenkette binär/ASCII-8BIT ist, wird die interne Kodierung der Zeichenkette auf nil gesetzt, da keine Transkodierung erforderlich ist.
Optionale Schlüsselwortargumente enc_opts spezifizieren Kodierungsoptionen.
Source
static VALUE
rb_io_set_encoding_by_bom(VALUE io)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
if (!(fptr->mode & FMODE_BINMODE)) {
rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
}
if (fptr->encs.enc2) {
rb_raise(rb_eArgError, "encoding conversion is set");
}
else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
rb_raise(rb_eArgError, "encoding is set to %s already",
rb_enc_name(fptr->encs.enc));
}
if (!io_set_encoding_by_bom(io)) return Qnil;
return rb_enc_from_encoding(fptr->encs.enc);
}
Wenn der Stream mit einem BOM (Byte Order Mark) beginnt, wird das BOM konsumiert und die externe Kodierung entsprechend gesetzt; gibt die Ergebnis-Kodierung zurück, wenn gefunden, oder nil andernfalls.
File.write('t.tmp', "\u{FEFF}abc") io = File.open('t.tmp', 'rb') io.set_encoding_by_bom # => #<Encoding:UTF-8> io.close File.write('t.tmp', 'abc') io = File.open('t.tmp', 'rb') io.set_encoding_by_bom # => nil io.close
Löst eine Ausnahme aus, wenn der Stream nicht im Binärmodus ist oder seine Kodierung bereits gesetzt wurde.
Source
static VALUE
rb_io_stat(VALUE obj)
{
rb_io_t *fptr;
rb_io_stat_data st;
GetOpenFile(obj, fptr);
if (fstatx_without_gvl(fptr, &st, STATX_ALL) == -1) {
rb_sys_fail_path(fptr->pathv);
}
return rb_statx_new(&st);
}
Gibt Statusinformationen für ios als Objekt vom Typ File::Stat zurück.
f = File.new("testfile") s = f.stat "%o" % s.mode #=> "100644" s.blksize #=> 4096 s.atime #=> Wed Apr 09 08:53:54 CDT 2003
Source
static VALUE
rb_io_sync(VALUE io)
{
rb_io_t *fptr;
io = GetWriteIO(io);
GetOpenFile(io, fptr);
return RBOOL(fptr->mode & FMODE_SYNC);
}
Gibt den aktuellen Synchronisationsmodus des Streams zurück. Wenn der Synchronisationsmodus true ist, wird die gesamte Ausgabe sofort an das zugrunde liegende Betriebssystem geleert und nicht intern von Ruby gepuffert. Siehe auch fsync.
f = File.open('t.tmp', 'w') f.sync # => false f.sync = true f.sync # => true f.close
Source
static VALUE
rb_io_set_sync(VALUE io, VALUE sync)
{
rb_io_t *fptr;
io = GetWriteIO(io);
GetOpenFile(io, fptr);
if (RTEST(sync)) {
fptr->mode |= FMODE_SYNC;
}
else {
fptr->mode &= ~FMODE_SYNC;
}
return sync;
}
Setzt den Sync-Modus für den Stream auf den gegebenen Wert; gibt den gegebenen Wert zurück.
Werte für den Sync-Modus
-
true: Alle Ausgaben werden sofort an das zugrunde liegende Betriebssystem geleert und nicht intern gepuffert. -
false: Die Ausgabe kann intern gepuffert werden.
Beispiel:
f = File.open('t.tmp', 'w') f.sync # => false f.sync = true f.sync # => true f.close
Verwandt: IO#fsync.
Source
static VALUE
rb_io_sysread(int argc, VALUE *argv, VALUE io)
{
VALUE len, str;
rb_io_t *fptr;
long n, ilen;
struct io_internal_read_struct iis;
int shrinkable;
rb_scan_args(argc, argv, "11", &len, &str);
ilen = NUM2LONG(len);
shrinkable = io_setstrbuf(&str, ilen);
if (ilen == 0) return str;
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
if (READ_DATA_BUFFERED(fptr)) {
rb_raise(rb_eIOError, "sysread for buffered IO");
}
rb_io_check_closed(fptr);
io_setstrbuf(&str, ilen);
iis.th = rb_thread_current();
iis.fptr = fptr;
iis.nonblock = 0;
iis.fd = fptr->fd;
iis.buf = RSTRING_PTR(str);
iis.capa = ilen;
iis.timeout = NULL;
n = io_read_memory_locktmp(str, &iis);
if (n < 0) {
rb_sys_fail_path(fptr->pathv);
}
io_set_read_length(str, n, shrinkable);
if (n == 0 && ilen > 0) {
rb_eof_error();
}
return str;
}
Verhält sich wie IO#readpartial, außer dass es Low-Level-Systemfunktionen verwendet.
Diese Methode sollte nicht mit anderen Stream-Reader-Methoden verwendet werden.
Source
static VALUE
rb_io_sysseek(int argc, VALUE *argv, VALUE io)
{
VALUE offset, ptrname;
int whence = SEEK_SET;
rb_io_t *fptr;
rb_off_t pos;
if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
whence = interpret_seek_whence(ptrname);
}
pos = NUM2OFFT(offset);
GetOpenFile(io, fptr);
if ((fptr->mode & FMODE_READABLE) &&
(READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
rb_raise(rb_eIOError, "sysseek for buffered IO");
}
if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
rb_warn("sysseek for buffered IO");
}
errno = 0;
pos = lseek(fptr->fd, pos, whence);
if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
return OFFT2NUM(pos);
}
Verhält sich wie IO#seek, außer dass es
-
verwendet Low-Level-Systemfunktionen.
-
gibt die neue Position zurück.
Source
static VALUE
rb_io_syswrite(VALUE io, VALUE str)
{
VALUE tmp;
rb_io_t *fptr;
long n, len;
const char *ptr;
if (!RB_TYPE_P(str, T_STRING))
str = rb_obj_as_string(str);
io = GetWriteIO(io);
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
if (fptr->wbuf.len) {
rb_warn("syswrite for buffered IO");
}
tmp = rb_str_tmp_frozen_acquire(str);
RSTRING_GETMEM(tmp, ptr, len);
n = rb_io_write_memory(fptr, ptr, len);
if (n < 0) rb_sys_fail_path(fptr->pathv);
rb_str_tmp_frozen_release(str, tmp);
return LONG2FIX(n);
}
Schreibt das gegebene object in self, das zum Schreiben geöffnet sein muss (siehe Zugriffsmodi); gibt die Anzahl der geschriebenen Bytes zurück. Wenn object keine Zeichenkette ist, wird es über die Methode to_s konvertiert.
f = File.new('t.tmp', 'w') f.syswrite('foo') # => 3 f.syswrite(30) # => 2 f.syswrite(:foo) # => 3 f.close
Diese Methode sollte nicht mit anderen Stream-Writer-Methoden verwendet werden.
Source
static VALUE
rb_io_tell(VALUE io)
{
rb_io_t *fptr;
rb_off_t pos;
GetOpenFile(io, fptr);
pos = io_tell(fptr);
if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
pos -= fptr->rbuf.len;
return OFFT2NUM(pos);
}
Gibt die aktuelle Position (in Bytes) in self zurück (siehe Position).
f = File.open('t.txt') f.tell # => 0 f.gets # => "First line\n" f.tell # => 12 f.close
Source
VALUE
rb_io_timeout(VALUE self)
{
rb_io_t *fptr = rb_io_get_fptr(self);
return fptr->timeout;
}
Holt die interne Timeout-Dauer oder nil, wenn sie nicht gesetzt wurde.
Source
VALUE
rb_io_set_timeout(VALUE self, VALUE timeout)
{
// Validate it:
if (RTEST(timeout)) {
rb_time_interval(timeout);
}
rb_io_t *fptr = rb_io_get_fptr(self);
fptr->timeout = timeout;
return self;
}
Setzt den internen Timeout auf die angegebene Dauer oder nil. Der Timeout gilt, wo immer möglich, für alle blockierenden Operationen.
Wenn eine Operation länger als das eingestellte Timeout dauert, wird IO::TimeoutError ausgelöst.
Dies betrifft die folgenden Methoden (ist aber nicht darauf beschränkt): gets, puts, read, write, wait_readable und wait_writable. Dies betrifft auch blockierende Socket-Operationen wie Socket#accept und Socket#connect.
Einige Operationen wie File#open und IO#close werden vom Timeout nicht beeinflusst. Ein Timeout während eines Schreibvorgangs kann den IO in einem inkonsistenten Zustand hinterlassen, z. B. wurden Daten teilweise geschrieben. Im Allgemeinen ist ein Timeout ein letzter Versuch, zu verhindern, dass eine Anwendung bei langsamen E/A-Operationen hängt, wie sie beispielsweise bei einem Slowloris-Angriff auftreten.
Source
static VALUE
console_ttyname(VALUE io)
{
int fd = rb_io_descriptor(io);
if (!isatty(fd)) return Qnil;
# if defined _WIN32
return rb_usascii_str_new_lit("con");
# elif defined HAVE_TTYNAME_R
{
char termname[1024], *tn = termname;
size_t size = sizeof(termname);
int e;
if (ttyname_r(fd, tn, size) == 0)
return rb_interned_str_cstr(tn);
if ((e = errno) == ERANGE) {
VALUE s = rb_str_new(0, size);
while (1) {
tn = RSTRING_PTR(s);
size = rb_str_capacity(s);
if (ttyname_r(fd, tn, size) == 0) {
return rb_str_to_interned_str(rb_str_resize(s, strlen(tn)));
}
if ((e = errno) != ERANGE) break;
if ((size *= 2) >= INT_MAX/2) break;
rb_str_resize(s, size);
}
}
rb_syserr_fail_str(e, rb_sprintf("ttyname_r(%d)", fd));
UNREACHABLE_RETURN(Qnil);
}
# elif defined HAVE_TTYNAME
{
const char *tn = ttyname(fd);
if (!tn) {
int e = errno;
rb_syserr_fail_str(e, rb_sprintf("ttyname(%d)", fd));
}
return rb_interned_str_cstr(tn);
}
# else
# error No ttyname function
# endif
}
Gibt den Namen des zugehörigen Terminals (tty) zurück, wenn io kein TTY ist. Gibt andernfalls nil zurück.
Source
VALUE
rb_io_ungetbyte(VALUE io, VALUE b)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
switch (TYPE(b)) {
case T_NIL:
return Qnil;
case T_FIXNUM:
case T_BIGNUM: ;
VALUE v = rb_int_modulo(b, INT2FIX(256));
unsigned char c = NUM2INT(v) & 0xFF;
b = rb_str_new((const char *)&c, 1);
break;
default:
StringValue(b);
}
io_ungetbyte(b, fptr);
return Qnil;
}
Schiebt die gegebenen Daten zurück ("unshifts") in den Puffer des Streams, sodass sie als nächstes gelesen werden; gibt nil zurück. Siehe Byte-E/A.
Beachten Sie, dass
-
Der Aufruf der Methode hat keine Auswirkung bei unbuffered Reads (wie
IO#sysread). -
Der Aufruf von
rewindauf dem Stream verwirft die zurückgeschobenen Daten.
Wenn das Argument integer gegeben ist, wird nur dessen niederwertigstes Byte verwendet.
File.write('t.tmp', '012') f = File.open('t.tmp') f.ungetbyte(0x41) # => nil f.read # => "A012" f.rewind f.ungetbyte(0x4243) # => nil f.read # => "C012" f.close
Wenn das Argument string gegeben ist, werden alle Bytes verwendet.
File.write('t.tmp', '012') f = File.open('t.tmp') f.ungetbyte('A') # => nil f.read # => "A012" f.rewind f.ungetbyte('BCDE') # => nil f.read # => "BCDE012" f.close
Source
VALUE
rb_io_ungetc(VALUE io, VALUE c)
{
rb_io_t *fptr;
long len;
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
if (FIXNUM_P(c)) {
c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
}
else if (RB_BIGNUM_TYPE_P(c)) {
c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
}
else {
StringValue(c);
}
if (NEED_READCONV(fptr)) {
SET_BINARY_MODE(fptr);
len = RSTRING_LEN(c);
#if SIZEOF_LONG > SIZEOF_INT
if (len > INT_MAX)
rb_raise(rb_eIOError, "ungetc failed");
#endif
make_readconv(fptr, (int)len);
if (fptr->cbuf.capa - fptr->cbuf.len < len)
rb_raise(rb_eIOError, "ungetc failed");
if (fptr->cbuf.off < len) {
MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
fptr->cbuf.ptr+fptr->cbuf.off,
char, fptr->cbuf.len);
fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
}
fptr->cbuf.off -= (int)len;
fptr->cbuf.len += (int)len;
MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
}
else {
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
io_ungetbyte(c, fptr);
}
return Qnil;
}
Schiebt die gegebenen Daten zurück ("unshifts") in den Puffer des Streams, sodass sie als nächstes gelesen werden; gibt nil zurück. Siehe Zeichen-E/A.
Beachten Sie, dass
-
Der Aufruf der Methode hat keine Auswirkung bei unbuffered Reads (wie
IO#sysread). -
Der Aufruf von
rewindauf dem Stream verwirft die zurückgeschobenen Daten.
Wenn das Argument integer gegeben ist, wird der Integer als Zeichen interpretiert.
File.write('t.tmp', '012') f = File.open('t.tmp') f.ungetc(0x41) # => nil f.read # => "A012" f.rewind f.ungetc(0x0442) # => nil f.getc.ord # => 1090 f.close
Wenn das Argument string gegeben ist, werden alle Zeichen verwendet.
File.write('t.tmp', '012') f = File.open('t.tmp') f.ungetc('A') # => nil f.read # => "A012" f.rewind f.ungetc("\u0442\u0435\u0441\u0442") # => nil f.getc.ord # => 1090 f.getc.ord # => 1077 f.getc.ord # => 1089 f.getc.ord # => 1090 f.close
Source
static VALUE
io_wait(int argc, VALUE *argv, VALUE io)
{
VALUE timeout = Qundef;
enum rb_io_event events = 0;
int return_io = 0;
if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
// We'd prefer to return the actual mask, but this form would return the io itself:
return_io = 1;
// Slow/messy path:
for (int i = 0; i < argc; i += 1) {
if (RB_SYMBOL_P(argv[i])) {
events |= wait_mode_sym(argv[i]);
}
else if (UNDEF_P(timeout)) {
rb_time_interval(timeout = argv[i]);
}
else {
rb_raise(rb_eArgError, "timeout given more than once");
}
}
if (UNDEF_P(timeout)) timeout = Qnil;
if (events == 0) {
events = RUBY_IO_READABLE;
}
}
else /* argc == 2 and neither are symbols */ {
// This is the fast path:
events = io_event_from_value(argv[0]);
timeout = argv[1];
}
if (events & RUBY_IO_READABLE) {
rb_io_t *fptr = NULL;
RB_IO_POINTER(io, fptr);
if (rb_io_read_pending(fptr)) {
// This was the original behaviour:
if (return_io) return Qtrue;
// New behaviour always returns an event mask:
else return RB_INT2NUM(RUBY_IO_READABLE);
}
}
return io_wait_event(io, events, timeout, return_io);
}
Wartet, bis der IO für die angegebenen Ereignisse bereit ist, und gibt die Teilmenge der Ereignisse zurück, die bereit werden, oder einen falsy-Wert, wenn ein Timeout auftritt.
Die Ereignisse können eine Bitmaske von IO::READABLE, IO::WRITABLE oder IO::PRIORITY sein.
Gibt sofort eine Ereignismaske (truthy-Wert) zurück, wenn gepufferte Daten verfügbar sind.
Die zweite Form: Wenn ein oder mehrere Ereignissymbole (:read, :write oder :read_write) übergeben werden, ist die Ereignismaske das bitweise OR der entsprechenden Bitmaske für diese Symbole. In dieser Form ist timeout optional, die Reihenfolge der Argumente ist beliebig und es wird io zurückgegeben, wenn eines der Ereignisse bereit ist.
Source
static VALUE
io_wait_priority(int argc, VALUE *argv, VALUE io)
{
rb_io_t *fptr = NULL;
RB_IO_POINTER(io, fptr);
rb_io_check_char_readable(fptr);
if (rb_io_read_pending(fptr)) return Qtrue;
rb_check_arity(argc, 0, 1);
VALUE timeout = argc == 1 ? argv[0] : Qnil;
return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
}
Wartet, bis IO Priorität hat, und gibt einen truthy-Wert oder einen falsy-Wert zurück, wenn ein Timeout auftritt. Prioritätsdaten werden mit dem Socket::MSG_OOB-Flag gesendet und empfangen und sind typischerweise auf Streams beschränkt.
Source
static VALUE
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
rb_io_t *fptr;
RB_IO_POINTER(io, fptr);
rb_io_check_char_readable(fptr);
if (rb_io_read_pending(fptr)) return Qtrue;
rb_check_arity(argc, 0, 1);
VALUE timeout = (argc == 1 ? argv[0] : Qnil);
return io_wait_event(io, RUBY_IO_READABLE, timeout, 1);
}
Wartet, bis IO lesbar ist, und gibt einen truthy-Wert zurück, oder einen falsy-Wert, wenn ein Timeout auftritt. Gibt sofort einen truthy-Wert zurück, wenn gepufferte Daten verfügbar sind.
Source
static VALUE
io_wait_writable(int argc, VALUE *argv, VALUE io)
{
rb_io_t *fptr;
RB_IO_POINTER(io, fptr);
rb_io_check_writable(fptr);
rb_check_arity(argc, 0, 1);
VALUE timeout = (argc == 1 ? argv[0] : Qnil);
return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
}
Wartet, bis IO schreibbar ist, und gibt einen truthy-Wert zurück, oder einen falsy-Wert, wenn ein Timeout auftritt.
Source
static VALUE
console_winsize(VALUE io)
{
rb_console_size_t ws;
int fd = GetWriteFD(io);
if (!getwinsize(fd, &ws)) sys_fail(io);
return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
}
Gibt die Konsolengröße zurück.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
console_set_winsize(VALUE io, VALUE size)
{
rb_console_size_t ws;
#if defined _WIN32
HANDLE wh;
int newrow, newcol;
COORD oldsize;
SMALL_RECT oldwindow;
BOOL ret;
#endif
VALUE row, col, xpixel, ypixel;
const VALUE *sz;
long sizelen;
int fd;
size = rb_Array(size);
if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) {
rb_raise(rb_eArgError, "wrong number of arguments (given %ld, expected 2 or 4)", sizelen);
}
sz = RARRAY_CONST_PTR(size);
row = sz[0], col = sz[1], xpixel = ypixel = Qnil;
if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
fd = GetWriteFD(io);
#if defined TIOCSWINSZ
ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
#define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
SET(row);
SET(col);
SET(xpixel);
SET(ypixel);
#undef SET
if (!setwinsize(fd, &ws)) sys_fail(io);
#elif defined _WIN32
wh = (HANDLE)rb_w32_get_osfhandle(fd);
#define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
SET(row);
SET(col);
#undef SET
if (!NIL_P(xpixel)) (void)NUM2UINT(xpixel);
if (!NIL_P(ypixel)) (void)NUM2UINT(ypixel);
if (!GetConsoleScreenBufferInfo(wh, &ws)) {
rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
}
oldsize = ws.dwSize;
oldwindow = ws.srWindow;
if (ws.srWindow.Right + 1 < newcol) {
ws.dwSize.X = newcol;
}
if (ws.dwSize.Y < newrow) {
ws.dwSize.Y = newrow;
}
/* expand screen buffer first if needed */
if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
}
/* refresh ws for new dwMaximumWindowSize */
if (!GetConsoleScreenBufferInfo(wh, &ws)) {
rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
}
/* check new size before modifying buffer content */
if (newrow <= 0 || newcol <= 0 ||
newrow > ws.dwMaximumWindowSize.Y ||
newcol > ws.dwMaximumWindowSize.X) {
SetConsoleScreenBufferSize(wh, oldsize);
/* remove scrollbar if possible */
SetConsoleWindowInfo(wh, TRUE, &oldwindow);
rb_raise(rb_eArgError, "out of range winsize: [%d, %d]", newrow, newcol);
}
/* shrink screen buffer width */
ws.dwSize.X = newcol;
/* shrink screen buffer height if window height were the same */
if (oldsize.Y == ws.srWindow.Bottom - ws.srWindow.Top + 1) {
ws.dwSize.Y = newrow;
}
ws.srWindow.Left = 0;
ws.srWindow.Right = newcol - 1;
ws.srWindow.Bottom = ws.srWindow.Top + newrow -1;
if (ws.dwCursorPosition.Y > ws.srWindow.Bottom) {
console_scroll(io, ws.dwCursorPosition.Y - ws.srWindow.Bottom);
ws.dwCursorPosition.Y = ws.srWindow.Bottom;
console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
}
if (ws.srWindow.Bottom > ws.dwSize.Y - 1) {
console_scroll(io, ws.srWindow.Bottom - (ws.dwSize.Y - 1));
ws.dwCursorPosition.Y -= ws.srWindow.Bottom - (ws.dwSize.Y - 1);
console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
ws.srWindow.Bottom = ws.dwSize.Y - 1;
}
ws.srWindow.Top = ws.srWindow.Bottom - (newrow - 1);
/* perform changes to winsize */
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
int last_error = LAST_ERROR;
SetConsoleScreenBufferSize(wh, oldsize);
rb_syserr_fail(last_error, "SetConsoleWindowInfo");
}
/* perform screen buffer shrinking if necessary */
if ((ws.dwSize.Y < oldsize.Y || ws.dwSize.X < oldsize.X) &&
!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
}
/* remove scrollbar if possible */
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
}
#endif
return io;
}
Versucht, die Konsolengröße zu setzen. Die Auswirkung hängt von der Plattform und der laufenden Umgebung ab.
Sie müssen 'io/console' erfordern, um diese Methode zu verwenden.
Source
static VALUE
io_write_m(int argc, VALUE *argv, VALUE io)
{
if (argc != 1) {
return io_writev(argc, argv, io);
}
else {
VALUE str = argv[0];
return io_write(io, str, 0);
}
}
Schreibt jedes der gegebenen objects in self, das zum Schreiben geöffnet sein muss (siehe Zugriffsmodi); gibt die Gesamtzahl der geschriebenen Bytes zurück; jedes der objects, das keine Zeichenkette ist, wird über die Methode to_s konvertiert.
$stdout.write('Hello', ', ', 'World!', "\n") # => 14 $stdout.write('foo', :bar, 2, "\n") # => 8
Ausgabe
Hello, World! foobar2
Verwandt: IO#read.
Source
# File io.rb, line 120 def write_nonblock(buf, exception: true) Primitive.io_write_nonblock(buf, exception) end
Schreibt den gegebenen String in ios unter Verwendung des write(2) Systemaufrufs, nachdem O_NONBLOCK für den zugrunde liegenden Dateideskriptor gesetzt wurde.
Gibt die Anzahl der geschriebenen Bytes zurück.
write_nonblock ruft lediglich den write(2) Systemaufruf auf. Dies verursacht alle Fehler, die der write(2) Systemaufruf verursacht: Errno::EWOULDBLOCK, Errno::EINTR, usw. Das Ergebnis kann auch kleiner als string.length sein (teilweises Schreiben). Der Aufrufer sollte sich um solche Fehler und teilweises Schreiben kümmern.
Wenn die Ausnahme Errno::EWOULDBLOCK oder Errno::EAGAIN ist, wird sie von IO::WaitWritable erweitert. Daher kann IO::WaitWritable verwendet werden, um die Ausnahmen für die Wiederholung von write_nonblock abzufangen.
# Creates a pipe. r, w = IO.pipe # write_nonblock writes only 65536 bytes and return 65536. # (The pipe size is 65536 bytes on this environment.) s = "a" * 100000 p w.write_nonblock(s) #=> 65536 # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN). p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN)
Wenn der Schreibpuffer nicht leer ist, wird er zuerst geleert.
Wenn write_nonblock eine Ausnahme vom Typ IO::WaitWritable auslöst, sollte write_nonblock erst aufgerufen werden, wenn io schreibbar ist, um eine Endlosschleife zu vermeiden. Dies kann wie folgt geschehen.
begin result = io.write_nonblock(string) rescue IO::WaitWritable, Errno::EINTR IO.select(nil, [io]) retry end
Beachten Sie, dass dies nicht garantiert, dass der gesamte String geschrieben wird. Die geschriebene Länge wird als Ergebnis angegeben und sollte später überprüft werden.
Auf einigen Plattformen wie Windows wird write_nonblock je nach Art des IO-Objekts nicht unterstützt. In solchen Fällen löst write_nonblock Errno::EBADF aus.
Durch Angabe des Schlüsselwortarguments exception auf false können Sie angeben, dass write_nonblock keine IO::WaitWritable Ausnahme auslösen, sondern das Symbol :wait_writable zurückgeben soll.