The IO
class is the basis for all input and output in Crystal.
This class is inherited by types like File
, Socket
and IO::Memory
and provides many useful methods for reading from and writing to an IO, like #print
, #puts
, #gets
and #printf
.
The only requirement for a type including the IO
module is to define these two methods:
#read(slice : Bytes)
: read at most slice.size bytes from IO into slice and return the number of bytes read#write(slice : Bytes)
: write the whole slice into the IOFor example, this is a simple IO
on top of a Bytes
:
class SimpleSliceIO < IO def initialize(@slice : Bytes) end def read(slice : Bytes) slice.size.times { |i| slice[i] = @slice[i] } @slice += slice.size slice.size end def write(slice : Bytes) : Nil slice.size.times { |i| @slice[i] = slice[i] } @slice += slice.size end end slice = Slice.new(9) { |i| ('a'.ord + i).to_u8 } String.new(slice) # => "abcdefghi" io = SimpleSliceIO.new(slice) io.gets(3) # => "abc" io.print "xyz" String.new(slice) # => "abcxyzghi"
An IO
can be set an encoding with the #set_encoding
method. When this is set, all string operations (#gets
, #gets_to_end
, #read_char
, #<<
, #print
, #puts
#printf
) will write in the given encoding, and read from the given encoding. Byte operations (#read
, #write
, #read_byte
, #write_byte
) never do encoding/decoding operations.
If an encoding is not set, the default one is UTF-8.
Mixing string and byte operations might not give correct results and should be avoided, as string operations might need to read extra bytes in order to get characters in the given encoding.
Copy at most limit bytes from src to dst.
Copy all contents from src to dst.
Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element Tuple
.
Creates a pair of pipe endpoints (connected to each other) and passes them to the given block.
Compares two streams stream1 to stream2 to determine if they are identical.
Writes the given object into this IO
.
Closes this IO
.
Returns true
if this IO
is closed.
Returns this IO
's encoding.
Flushes buffered data, if any.
Reads until delimiter is found, limit bytes are read, or the end of the IO
is reached.
Reads until delimiter is found, or the end of the IO
is reached.
Reads a line from this IO
.
Reads a line of at most limit bytes from this IO
.
Reads until delimiter is found or the end of the IO
is reached.
Peeks into this IO, if possible.
Returns the current position (in bytes) in this IO
.
Sets the current position (in bytes) in this IO
.
Writes the given objects into this IO
by invoking to_s(io)
on each of the objects.
Same as #<<
.
Writes a formatted string to this IO.
Writes a formatted string to this IO.
Writes the given objects, each followed by a newline character.
Writes a newline character.
Writes the given object to this IO
followed by a newline character.
Writes the given string to this IO
followed by a newline character unless the string already ends with one.
Reads at most slice.size bytes from this IO
into slice.
Yields an IO
to read a section inside this IO.
Reads a single byte from this IO
.
Reads an instance of the given type from this IO
using the specified format.
Tries to read exactly slice.size
bytes from this IO
into slice.
Tries to read exactly slice.size
bytes from this IO
into slice.
Reads an UTF-8 encoded string of exactly bytesize bytes.
Reads UTF-8 decoded bytes into the given slice.
Reads a single decoded UTF-8 byte from this IO
.
Rewinds this IO
.
Seeks to a given offset (in bytes) according to the whence argument.
Sets the encoding of this IO
.
Reads and discards exactly bytes_count bytes.
Reads and discards bytes from self
until there are no more bytes.
Same as #pos
.
Returns true
if this IO
is associated with a terminal device (tty), false
otherwise.
Writes the contents of slice into this IO
.
Writes a single byte into this IO
.
Writes the given object to this IO
using the specified format.
Writes a slice of UTF-8 encoded bytes to this IO
, using the current encoding.
Reference
Reference
Object
Object
Copy at most limit bytes from src to dst.
io = IO::Memory.new "hello" io2 = IO::Memory.new IO.copy io, io2, 3 io2.to_s # => "hel"
Copy all contents from src to dst.
io = IO::Memory.new "hello" io2 = IO::Memory.new IO.copy io, io2 io2.to_s # => "hello"
Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element Tuple
.
reader, writer = IO.pipe writer.puts "hello" writer.puts "world" reader.gets # => "hello" reader.gets # => "world"
Creates a pair of pipe endpoints (connected to each other) and passes them to the given block. Both endpoints are closed after the block.
IO.pipe do |reader, writer| writer.puts "hello" writer.puts "world" reader.gets # => "hello" reader.gets # => "world" end
Compares two streams stream1 to stream2 to determine if they are identical. Returns true
if content are the same, false
otherwise.
File.write("afile", "123") stream1 = File.open("afile") stream2 = IO::Memory.new("123") IO.same_content?(stream1, stream2) # => true
Writes the given object into this IO
. This ends up calling to_s(io)
on the object.
io = IO::Memory.new io << 1 io << '-' io << "Crystal" io.to_s # => "1-Crystal"
Flushes buffered data, if any.
IO
defines this is a no-op method, but including types may override.
Reads a line from this IO
. A line is terminated by the \n
character. Returns nil
if called at the end of this IO
.
By default the newline is removed from the returned string, unless chomp is false
.
io = IO::Memory.new "hello\nworld\nfoo\n" io.gets # => "hello" io.gets(chomp: false) # => "world\n" io.gets # => "foo" io.gets # => nil
Peeks into this IO, if possible.
It returns:
nil
if this IO isn't peekableThe returned bytes are only valid data until a next call to any method that reads from this IO is invoked.
By default this method returns nil
, but IO implementations that provide buffering or wrap other IOs should override this method.
Returns the current position (in bytes) in this IO
.
The IO
class raises on this method, but some subclasses, notable IO::FileDescriptor
and IO::Memory
implement it.
File.write("testfile", "hello") file = File.new("testfile") file.pos # => 0 file.gets(2) # => "he" file.pos # => 2
Sets the current position (in bytes) in this IO
.
The IO
class raises on this method, but some subclasses, notable IO::FileDescriptor
and IO::Memory
implement it.
File.write("testfile", "hello") file = File.new("testfile") file.pos = 3 file.gets_to_end # => "lo"
Writes the given objects into this IO
by invoking to_s(io)
on each of the objects.
io = IO::Memory.new io.print 1, '-', "Crystal" io.to_s # => "1-Crystal"
Same as #<<
.
io = IO::Memory.new io.print 1 io.print '-' io.print "Crystal" io.to_s # => "1-Crystal"
Writes a formatted string to this IO. For details on the format string, see Kernel::sprintf
.
Writes a formatted string to this IO. For details on the format string, see Kernel::sprintf
.
Writes the given objects, each followed by a newline character.
io = IO::Memory.new io.puts 1, '-', "Crystal" io.to_s # => "1\n-\nCrystal\n"
Writes the given object to this IO
followed by a newline character.
io = IO::Memory.new io.puts 1 io.puts "Crystal" io.to_s # => "1\nCrystal\n"
Writes the given string to this IO
followed by a newline character unless the string already ends with one.
io = IO::Memory.new io.puts "hello\n" io.puts "world" io.to_s # => "hello\nworld\n"
Reads at most slice.size bytes from this IO
into slice. Returns the number of bytes read, which is 0 if and only if there is no more data to read (so checking for 0 is the way to detect end of file).
io = IO::Memory.new "hello" slice = Bytes.new(4) io.read(slice) # => 4 slice # => Bytes[104, 101, 108, 108] io.read(slice) # => 1 slice # => Bytes[111, 101, 108, 108] io.read(slice) # => 0
Yields an IO
to read a section inside this IO.
The IO
class raises on this method, but some subclasses, notable File
and IO::Memory
implement it.
Multiple sections can be read concurrently.
Reads a single byte from this IO
. Returns nil
if there is no more data to read.
io = IO::Memory.new "a" io.read_byte # => 97 io.read_byte # => nil
Reads an instance of the given type from this IO
using the specified format.
This ends up invoking type.from_io(self, format)
, so any type defining a from_io(io : IO, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
method can be read in this way.
See Int.from_io
and Float.from_io
.
io = IO::Memory.new io.puts "\u{4}\u{3}\u{2}\u{1}" io.rewind io.read_bytes(Int32, IO::ByteFormat::LittleEndian) # => 0x01020304
Tries to read exactly slice.size
bytes from this IO
into slice. Returns nil
if there aren't slice.size
bytes of data, otherwise returns the number of bytes read.
io = IO::Memory.new "123451234" slice = Bytes.new(5) io.read_fully?(slice) # => 5 slice # => Bytes[49, 50, 51, 52, 53] io.read_fully?(slice) # => nil
Reads an UTF-8 encoded string of exactly bytesize bytes. Raises EOFError
if there are not enough bytes to build the string.
io = IO::Memory.new("hello world") io.read_string(5) # => "hello" io.read_string(1) # => " " io.read_string(6) # raises IO::EOFError
Reads UTF-8 decoded bytes into the given slice. Returns the number of UTF-8 bytes read.
If no encoding is set, this is the same as #read(slice)
.
bytes = "你".encode("GB2312") # => Bytes[196, 227] io = IO::Memory.new(bytes) io.set_encoding("GB2312") buffer = uninitialized UInt8[1024] bytes_read = io.read_utf8(buffer.to_slice) # => 3 buffer.to_slice[0, bytes_read] # => Bytes[228, 189, 160] "你".bytes # => [228, 189, 160]
Reads a single decoded UTF-8 byte from this IO
. Returns nil
if there is no more data to read.
If no encoding is set, this is the same as #read_byte
.
bytes = "你".encode("GB2312") # => Bytes[196, 227] io = IO::Memory.new(bytes) io.set_encoding("GB2312") io.read_utf8_byte # => 228 io.read_utf8_byte # => 189 io.read_utf8_byte # => 160 io.read_utf8_byte # => nil "你".bytes # => [228, 189, 160]
Rewinds this IO
. By default this method raises, but including types may implement it.
Seeks to a given offset (in bytes) according to the whence argument.
The IO
class raises on this method, but some subclasses, notable IO::FileDescriptor
and IO::Memory
implement it.
Returns self
.
File.write("testfile", "abc") file = File.new("testfile") file.gets(3) # => "abc" file.seek(1, IO::Seek::Set) file.gets(2) # => "bc" file.seek(-1, IO::Seek::Current) file.gets(1) # => "c"
Sets the encoding of this IO
.
The invalid argument can be:
nil
: an exception is raised on invalid byte sequences:skip
: invalid byte sequences are ignoredString operations (#gets
, #gets_to_end
, #read_char
, #<<
, #print
, #puts
#printf
) will use this encoding.
Reads and discards exactly bytes_count bytes. Raises IO::EOFError
if there aren't at least bytes_count bytes.
io = IO::Memory.new "hello world" io.skip(6) io.gets # => "world" io.skip(1) # raises IO::EOFError
Returns true
if this IO
is associated with a terminal device (tty), false
otherwise.
IO returns false
, but including types may override.
STDIN.tty? # => true IO::Memory.new.tty? # => false
Writes the contents of slice into this IO
.
io = IO::Memory.new slice = Bytes.new(4) { |i| ('a'.ord + i).to_u8 } io.write(slice) io.to_s # => "abcd"
Writes a single byte into this IO
.
io = IO::Memory.new io.write_byte 97_u8 io.to_s # => "a"
Writes the given object to this IO
using the specified format.
This ends up invoking object.to_io(self, format)
, so any object defining a to_io(io : IO, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
method can be written in this way.
See Int#to_io
and Float#to_io
.
io = IO::Memory.new io.write_bytes(0x01020304, IO::ByteFormat::LittleEndian) io.rewind io.gets(4) # => "\u{4}\u{3}\u{2}\u{1}"
Writes a slice of UTF-8 encoded bytes to this IO
, using the current encoding.
© 2012–2020 Manas Technology Solutions.
Licensed under the Apache License, Version 2.0.
https://crystal-lang.org/api/0.35.1/IO.html