IO
module IO
Overview
The IO
module is the basis for all input and output in Crystal-
This module is included by types like File
, Socket
and IO::Memory
and provide many useful methods for reading to and writing from 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 into slice and return the number of bytes read -
#write(slice : Bytes)
: write the whole slice into the IO
For example, this is a simple IO
on top of a Bytes
:
class SimpleSliceIO include 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) slice.size.times { |i| @slice[i] = slice[i] } @slice += slice.size nil 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"
Encoding
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.
Direct including types
- Flate::Reader
- Flate::Writer
- Gzip::Reader
- Gzip::Writer
- HTTP::Server::Response
- HTTP::WebSocket::Protocol::StreamIO
- IO::Buffered
- IO::Delimited
- IO::Hexdump
- IO::Memory
- IO::MultiWriter
- IO::Sized
- String::Builder
- Zlib::Reader
- Zlib::Writer
Defined in:
io.crio/delimited.cr
io/encoding.cr
io/error.cr
io/hexdump.cr
io/multi_writer.cr
io/sized.cr
Class Method Summary
- .copy(src, dst, limit : Int)
Copy at most limit bytes from src to dst.
- .copy(src, dst)
Copy all contents from src to dst.
- .pipe(read_blocking = false, write_blocking = false)
Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element
Tuple
. - .pipe(read_blocking = false, write_blocking = false, &block)
Creates a pair of pipe endpoints (connected to each other) and passes them to the given block.
- .select(read_ios, write_ios, error_ios, timeout_sec : LibC::TimeT | Int | Float?)
Returns an array of all given IOs that are * ready to read if they appeared in read_ios * ready to write if they appeared in write_ios * have an error condition if they appeared in error_ios
- .select(read_ios, write_ios = nil, error_ios = nil)
Instance Method Summary
- #<<(obj) : self
Writes the given object into this
IO
- - #close
Closes this
IO
- - #closed?
Returns
true
if thisIO
is closed- - #each_byte
- #each_byte(&block) : Nil
- #each_char(&block) : Nil
- #each_char
- #each_line(*args, **options, &block) : Nil
- #each_line(*args, **options)
- #encoding : String
Returns this
IO
's encoding- - #flush
Flushes buffered data, if any.
- #gets(limit : Int, chomp = false) : String?
Reads a line of at most limit bytes from this
IO
- - #gets(delimiter : Char, chomp = false) : String?
Reads until delimiter is found, or the end of the
IO
is reached- - #gets(delimiter : String, chomp = false) : String?
Reads until delimiter is found or the end of the
IO
is reached- - #gets(chomp = true) : String?
Reads a line from this
IO
- - #gets(delimiter : Char, limit : Int, chomp = false) : String?
Reads until delimiter is found, limit bytes are read, or the end of the
IO
is reached- - #gets_to_end : String
- #peek : Bytes?
Peeks into this IO, if possible.
- #print(*objects : _) : Nil
Writes the given objects into this
IO
by invokingto_s(io)
on each of the objects- - #print(obj) : Nil
Same as
#<<
. - #printf(format_string, args : Array | Tuple) : Nil
- #printf(format_string, *args) : Nil
- #puts(*objects : _) : Nil
Writes the given objects, each followed by a newline character.
- #puts : Nil
Writes a newline character.
- #puts(obj) : Nil
Writes the given object to this
IO
followed by a newline character- - #puts(string : String) : Nil
Writes the given string to this
IO
followed by a newline character unless the string already ends with one- - #read(slice : Bytes)
Reads at most slice.size bytes from this
IO
into slice- - #read_byte : UInt8?
Reads a single byte from this
IO
- - #read_bytes(type, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
Reads an instance of the given type from this
IO
using the specified format- - #read_char : Char?
- #read_fully(slice : Bytes)
Tries to read exactly
slice.size
bytes from thisIO
into slice- - #read_fully?(slice : Bytes)
Tries to read exactly
slice.size
bytes from thisIO
into slice- - #read_line(*args, **options) : String?
- #read_string(bytesize : Int) : String
Reads an UTF-8 encoded string of exactly bytesize bytes.
- #read_utf8(slice : Bytes)
Reads UTF-8 decoded bytes into the given slice.
- #read_utf8_byte
Reads a single decoded UTF-8 byte from this
IO
- - #rewind
Rewinds this
IO
- - #set_encoding(encoding : String, invalid : Symbol? = nil)
Sets the encoding of this
IO
- - #skip(bytes_count : Int) : Nil
Reads and discards exactly bytes_count bytes.
- #skip_to_end : Nil
Reads and discards bytes from
self
until there are no more bytes. - #tty? : Bool
Returns
true
if thisIO
is associated with a terminal device (tty),false
otherwise- - #write(slice : Bytes) : Nil
Writes the contents of slice into this
IO
- - #write_byte(byte : UInt8)
Writes a single byte into this
IO
- - #write_bytes(object, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
Writes the given object to this
IO
using the specified format- - #write_utf8(slice : Bytes)
Writes a slice of UTF-8 encoded bytes to this
IO
, using the current encoding-
Class Method Detail
def self.copy(src, dst, limit : Int)Source
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"
def self.copy(src, dst)Source
Copy all contents from src to dst.
io = IO::Memory.new "hello" io2 = IO::Memory.new IO.copy io, io2 io2.to_s # => "hello"
def self.pipe(read_blocking = false, write_blocking = false)Source
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"
def self.pipe(read_blocking = false, write_blocking = false, &block)Source
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
def self.select(read_ios, write_ios, error_ios, timeout_sec : LibC::TimeT | Int | Float?)Source
Returns an array of all given IOs that are
- ready to read if they appeared in read_ios
- ready to write if they appeared in write_ios
- have an error condition if they appeared in error_ios
If the optional timeout_sec is given, nil
is returned if no IO
was ready after the specified amount of seconds passed- Fractions are supported-
If timeout_sec is nil
, this method blocks until an IO
is ready.
def self.select(read_ios, write_ios = nil, error_ios = nil)Source
Instance Method Detail
def <<(obj) : selfSource
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"
def closeSource
def closed?Source
def each_byteSource
def each_charSource
def each_line(*args, **options)Source
def flushSource
Flushes buffered data, if any.
IO
defines this is a no-op method, but including types may override-
def gets(chomp = true) : String?Source
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
def peek : Bytes?Source
Peeks into this IO, if possible.
It returns:
-
nil
if this IO isn't peekable - an empty slice if it is, but EOF was reached
- a non-empty slice if some data can be peeked
The 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.
def print(*objects : _) : NilSource
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"
def print(obj) : NilSource
Same as #<<
.
io = IO::Memory.new io.print 1 io.print '-' io.print "Crystal" io.to_s # => "1-Crystal"
def puts(*objects : _) : NilSource
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"
def puts(obj) : NilSource
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"
def puts(string : String) : NilSource
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"
abstract def read(slice : Bytes)Source
Reads at most slice.size bytes from this IO
into slice- Returns the number of bytes read-
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]
def read_byte : UInt8?Source
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
def read_bytes(type, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)Source
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
def read_fully?(slice : Bytes)Source
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
def read_string(bytesize : Int) : StringSource
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
def read_utf8(slice : Bytes)Source
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]
def read_utf8_byteSource
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]
def rewindSource
Rewinds this IO
- By default this method raises, but including types may implement it-
def set_encoding(encoding : String, invalid : Symbol? = nil)Source
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 ignored
String operations (#gets
, #gets_to_end
, #read_char
, #<<
, #print
, #puts
#printf
) will use this encoding.
def skip(bytes_count : Int) : NilSource
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
def tty? : BoolSource
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
abstract def write(slice : Bytes) : NilSource
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"
def write_byte(byte : UInt8)Source
Writes a single byte into this IO
-
io = IO::Memory.new io.write_byte 97_u8 io.to_s # => "a"
def write_bytes(object, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)Source
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}"
def write_utf8(slice : Bytes)Source
Writes a slice of UTF-8 encoded bytes to this IO
, using the current encoding-
© 2012–2017 Manas Technology Solutions.
Licensed under the Apache License, Version 2.0.
https://crystal-lang.org/api/0.22.0/IO.html