class StringIO

Die Klasse StringIO unterstützt den Zugriff auf einen String als Stream, in mancher Hinsicht ähnlich der Klasse IO.

Sie können eine StringIO-Instanz mit

Wie ein IO-Stream hat ein StringIO-Stream bestimmte Eigenschaften

Über die Beispiele

Die Beispiele auf dieser Seite gehen davon aus, dass StringIO bereits eingebunden wurde

require 'stringio'

Und dass diese Konstante definiert wurde

TEXT = <<EOT
First line
Second line

Fourth line
Fifth line
EOT

Stream-Eigenschaften

Lese-/Schreibmodus

Zusammenfassung

Modus Anfangs gelöscht? Lesen Schreiben
'r': schreibgeschützt Nein Überall Error
'w': schreibgeschützt Ja Error Überall
'a': nur anhängen Nein Error Nur am Ende
'r+': lesen/schreiben Nein Überall Überall
'w+': lesen/schreiben Ja Überall Überall
'a+': lesen/anhängen Nein Überall Nur am Ende

Jeder Abschnitt unten beschreibt einen Lese-/Schreibmodus.

Jeder der Modi kann als String oder als Dateikonstante angegeben werden; Beispiel

strio = StringIO.new('foo', 'a')
strio = StringIO.new('foo', File::WRONLY | File::APPEND)

'r': Nur Lesen

Modus angegeben als einer von

Anfangszustand

strio = StringIO.new('foobarbaz', 'r')
strio.pos    # => 0            # Beginning-of-stream.
strio.string # => "foobarbaz"  # Not cleared.

Kann überall gelesen werden

strio.gets(3) # => "foo"
strio.gets(3) # => "bar"
strio.pos = 9
strio.gets(3) # => nil

Kann nicht geschrieben werden

strio.write('foo')  # Raises IOError: not opened for writing

'w': Nur Schreiben

Modus angegeben als einer von

Anfangszustand

strio = StringIO.new('foo', 'w')
strio.pos    # => 0   # Beginning of stream.
strio.string # => ""  # Initially cleared.

Kann überall geschrieben werden (auch über das Ende des Streams hinaus)

strio.write('foobar')
strio.string # => "foobar"
strio.rewind
strio.write('FOO')
strio.string # => "FOObar"
strio.pos = 3
strio.write('BAR')
strio.string # => "FOOBAR"
strio.pos = 9
strio.write('baz')
strio.string # => "FOOBAR\u0000\u0000\u0000baz"  # Null-padded.

Kann nicht gelesen werden

strio.read  # Raises IOError: not opened for reading

'a': Nur Anhängen

Modus angegeben als einer von

Anfangszustand

strio = StringIO.new('foo', 'a')
strio.pos    # => 0      # Beginning-of-stream.
strio.string # => "foo"  # Not cleared.

Kann nur am Ende geschrieben werden; die Position beeinflusst das Schreiben nicht

strio.write('bar')
strio.string # => "foobar"
strio.write('baz')
strio.string # => "foobarbaz"
strio.pos = 400
strio.write('bat')
strio.string # => "foobarbazbat"

Kann nicht gelesen werden

strio.gets  # Raises IOError: not opened for reading

'r+': Lesen/Schreiben

Modus angegeben als einer von

Anfangszustand

strio = StringIO.new('foobar', 'r+')
strio.pos    # => 0         # Beginning-of-stream.
strio.string # => "foobar"  # Not cleared.

Kann überall geschrieben werden (auch über das Ende des Streams hinaus)

strio.write('FOO')
strio.string # => "FOObar"
strio.write('BAR')
strio.string # => "FOOBAR"
strio.write('BAZ')
strio.string # => "FOOBARBAZ"
strio.pos = 12
strio.write('BAT')
strio.string # => "FOOBARBAZ\u0000\u0000\u0000BAT"  # Null padded.

Kann überall gelesen werden

strio.pos = 0
strio.gets(3) # => "FOO"
strio.pos = 6
strio.gets(3) # => "BAZ"
strio.pos = 400
strio.gets(3) # => nil

'w+': Lesen/Schreiben (Anfangs gelöscht)

Modus angegeben als einer von

Anfangszustand

strio = StringIO.new('foo', 'w+')
strio.pos    # => 0   # Beginning-of-stream.
strio.string # => ""  # Truncated.

Kann überall geschrieben werden (auch über das Ende des Streams hinaus)

strio.write('foobar')
strio.string # => "foobar"
strio.rewind
strio.write('FOO')
strio.string # => "FOObar"
strio.write('BAR')
strio.string # => "FOOBAR"
strio.write('BAZ')
strio.string # => "FOOBARBAZ"
strio.pos = 12
strio.write('BAT')
strio.string # => "FOOBARBAZ\u0000\u0000\u0000BAT"  # Null-padded.

Kann überall gelesen werden

strio.rewind
strio.gets(3) # => "FOO"
strio.gets(3) # => "BAR"
strio.pos = 12
strio.gets(3) # => "BAT"
strio.pos = 400
strio.gets(3) # => nil

'a+': Lesen/Anhängen

Modus angegeben als einer von

Anfangszustand

strio = StringIO.new('foo', 'a+')
strio.pos    # => 0      # Beginning-of-stream.
strio.string # => "foo"  # Not cleared.

Kann nur am Ende geschrieben werden; rewind; die Position beeinflusst das Schreiben nicht

strio.write('bar')
strio.string # => "foobar"
strio.write('baz')
strio.string # => "foobarbaz"
strio.pos = 400
strio.write('bat')
strio.string # => "foobarbazbat"

Kann überall gelesen werden

strio.rewind
strio.gets(3) # => "foo"
strio.gets(3) # => "bar"
strio.pos = 9
strio.gets(3) # => "bat"
strio.pos = 400
strio.gets(3) # => nil

Data Modus

Um anzugeben, ob der Stream als Text oder als Binärdaten behandelt werden soll, kann einer der folgenden Suffixe an jeden der obigen String-Lese-/Schreibmodi angehängt werden

Wenn keiner angegeben ist, ist der Stream standardmäßig Textdaten.

Beispiele

strio = StringIO.new('foo', 'rt')
strio.external_encoding # => #<Encoding:UTF-8>
data = "\u9990\u9991\u9992\u9993\u9994"
strio = StringIO.new(data, 'rb')
strio.external_encoding # => #<Encoding:BINARY (ASCII-8BIT)>

Wenn der Datenmodus angegeben ist, darf der Lese-/Schreibmodus nicht weggelassen werden

StringIO.new(data, 'b')  # Raises ArgumentError: invalid access mode b

Ein Text-Stream kann durch Aufrufen der Instanzmethode binmode in einen Binär-Stream geändert werden; ein Binär-Stream kann nicht in einen Text-Stream geändert werden.

Kodierungen

Ein Stream hat eine Kodierung; siehe Kodierungen.

Die anfängliche Kodierung für einen neuen oder wiedereröffneten Stream hängt von seinem Datenmodus ab

Diese Instanzmethoden sind relevant

Beispiele

strio = StringIO.new('foo', 'rt')  # Text mode.
strio.external_encoding # => #<Encoding:UTF-8>
data = "\u9990\u9991\u9992\u9993\u9994"
strio = StringIO.new(data, 'rb') # Binary mode.
strio.external_encoding # => #<Encoding:BINARY (ASCII-8BIT)>
strio = StringIO.new('foo')
strio.external_encoding # => #<Encoding:UTF-8>
strio.set_encoding('US-ASCII')
strio.external_encoding # => #<Encoding:US-ASCII>

Position

Ein Stream hat eine Position, einen Integer-Offset (in Bytes) im Stream. Die anfängliche Position eines Streams ist Null.

Abrufen und Setzen der Position

Jede dieser Methoden initialisiert (auf Null) die Position eines neuen oder wiedereröffneten Streams

Jede dieser Methoden fragt ab, ruft ab oder setzt die Position, ohne den Stream anderweitig zu ändern

Beispiele

strio = StringIO.new('foobar')
strio.pos  # => 0
strio.pos = 3
strio.pos  # => 3
strio.eof? # => false
strio.rewind
strio.pos  # => 0
strio.seek(0, IO::SEEK_END)
strio.pos  # => 6
strio.eof? # => true

Position vor und nach dem Lesen

Mit Ausnahme von pread beginnt eine Stream-Lesemethode (siehe Grundlegendes Lesen) mit dem Lesen an der aktuellen Position.

Mit Ausnahme von pread verschiebt eine Lesemethode die Position über den gelesenen Teilstring.

Beispiele

strio = StringIO.new(TEXT)
strio.string # => "First line\nSecond line\n\nFourth line\nFifth line\n"
strio.pos    # => 0
strio.getc   # => "F"
strio.pos    # => 1
strio.gets   # => "irst line\n"
strio.pos    # => 11
strio.pos = 24
strio.gets   # => "Fourth line\n"
strio.pos    # => 36

strio = StringIO.new('тест') # Four 2-byte characters.
strio.pos = 0 # At first byte of first character.
strio.read    # => "тест"
strio.pos = 1 # At second byte of first character.
strio.read    # => "\x82ест"
strio.pos = 2 # At first of second character.
strio.read    # => "ест"

strio = StringIO.new(TEXT)
strio.pos = 15
a = []
strio.each_line {|line| a.push(line) }
a         # => ["nd line\n", "\n", "Fourth line\n", "Fifth line\n"]
strio.pos # => 47  ## End-of-stream.

Position vor und nach dem Schreiben

Jede dieser Methoden beginnt mit dem Schreiben an der aktuellen Position und verschiebt die Position bis zum Ende des geschriebenen Teilstrings

Beispiele

strio = StringIO.new('foo')
strio.pos    # => 0
strio.putc('b')
strio.string # => "boo"
strio.pos    # => 1
strio.write('r')
strio.string # => "bro"
strio.pos    # => 2
strio.puts('ew')
strio.string # => "brew\n"
strio.pos    # => 5
strio.pos = 8
strio.write('foo')
strio.string # => "brew\n\u0000\u0000\u0000foo"
strio.pos    # => 11

Jede dieser Methoden schreibt *vor* die aktuelle Position und dekrementiert die Position, sodass die geschriebenen Daten als nächstes gelesen werden können

Beispiele

strio = StringIO.new('foo')
strio.pos = 2
strio.ungetc('x')
strio.pos    # => 1
strio.string # => "fxo"
strio.ungetc('x')
strio.pos    # => 0
strio.string # => "xxo"

Diese Methode hat keinen Einfluss auf die Position

Beispiele

strio = StringIO.new('foobar')
strio.pos    # => 0
strio.truncate(3)
strio.string # => "foo"
strio.pos    # => 0
strio.pos = 500
strio.truncate(0)
strio.string # => ""
strio.pos    # => 500

Zeilennummer

Ein Stream hat eine Zeilennummer, die anfangs Null ist

Die Zeilennummer kann durch Lesen beeinflusst werden (aber niemals durch Schreiben); im Allgemeinen wird die Zeilennummer jedes Mal erhöht, wenn der Aufzeichnungstrennzeichen (Standard: "\n") gelesen wird.

Beispiele

strio = StringIO.new(TEXT)
strio.string # => "First line\nSecond line\n\nFourth line\nFifth line\n"
strio.lineno # => 0
strio.gets   # => "First line\n"
strio.lineno # => 1
strio.getc   # => "S"
strio.lineno # => 1
strio.gets   # => "econd line\n"
strio.lineno # => 2
strio.gets   # => "\n"
strio.lineno # => 3
strio.gets   # => "Fourth line\n"
strio.lineno # => 4

Das Setzen der Position beeinflusst die Zeilennummer nicht

strio.pos = 0
strio.lineno # => 4
strio.gets   # => "First line\n"
strio.pos    # => 11
strio.lineno # => 5

Und das Setzen der Zeilennummer beeinflusst die Position nicht

strio.lineno = 10
strio.pos    # => 11
strio.gets   # => "Second line\n"
strio.lineno # => 11
strio.pos    # => 23

Geöffnete/Geschlossene Streams

Ein neuer Stream ist zum Lesen oder Schreiben geöffnet und kann für beides geöffnet sein; siehe Lese-/Schreibmodus.

Jede dieser Methoden initialisiert den Lese-/Schreibmodus für einen neuen oder wiedereröffneten Stream

Andere relevante Methoden

BOM (Byte Order Mark)

Der String, der für ::new, ::open oder reopen bereitgestellt wird, kann ein optionales BOM (Byte Order Mark) am Anfang des Strings enthalten; das BOM kann die Kodierung des Streams beeinflussen.

Das BOM (falls vorhanden)

utf8_bom = "\xEF\xBB\xBF"
string = utf8_bom + 'foo'
string.bytes               # => [239, 187, 191, 102, 111, 111]
strio.string.bytes.take(3) # => [239, 187, 191]                  # The BOM.
strio = StringIO.new(string, 'rb')
strio.string.bytes         # => [239, 187, 191, 102, 111, 111]   # BOM is part of the stored string.
strio.external_encoding    # => #<Encoding:BINARY (ASCII-8BIT)>  # Default for a binary stream.
strio.gets                 # => "\xEF\xBB\xBFfoo"                # BOM is part of the stream.

Sie können die Instanzmethode set_encoding_by_bom aufrufen, um das gespeicherte BOM zu „aktivieren“; danach das BOM

strio.set_encoding_by_bom
strio.string.bytes      # => [239, 187, 191, 102, 111, 111]  # BOM is still part of the stored string.
strio.external_encoding # => #<Encoding:UTF-8>               # The new encoding.
strio.rewind            # => 0
strio.gets              # => "foo"                           # BOM is not part of the stream.

Grundlegende Stream-IO

Grundlegendes Lesen

Sie können aus dem Stream mit diesen Instanzmethoden lesen

Sie können den Stream mit diesen Instanzmethoden durchlaufen

Diese Instanzmethode ist in einer Multi-Threaded-Anwendung nützlich

Grundlegendes Schreiben

Sie können in den Stream schreiben und dabei die Position verschieben, mit diesen Instanzmethoden

Sie können in den Stream „zurückschieben“ mit diesen Instanzmethoden; jede schreibt *vor* die aktuelle Position und dekrementiert die Position, sodass die geschriebenen Daten als nächstes gelesen werden.

Eine weitere Schreibmethode

Zeilen-IO

Lesen

Schreiben

Zeichen-IO

Lesen

Schreiben

Byte-IO

Lesen

Schreiben

Codepunkt-IO

Lesen