abstract class IO
Overview
TheIO class is the basis for all input and output in Crystal.
This class is inherited by types likeFile,Socket andIO::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 theIO module is to define
these two methods:
#read(slice : Bytes): read at mostslice.size bytes from IO intoslice and return the number of bytes read#write(slice : Bytes): write the wholeslice into the IO
For example, this is a simpleIO on top of aBytes:
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"
Encoding
AnIO 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,#getb_to_end) 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 Known Subclasses
- Compress::Deflate::Reader
- Compress::Deflate::Writer
- Compress::Gzip::Reader
- Compress::Gzip::Writer
- Compress::Zlib::Reader
- Compress::Zlib::Writer
- HTTP::Server::Response
- IO::Delimited
- IO::Digest
- IO::FileDescriptor
- IO::Hexdump
- IO::Memory
- IO::MultiWriter
- IO::PrefixSuffixBuffer
- IO::Sized
- IO::Stapled
- OpenSSL::SSL::Socket
- Socket
- String::Builder
Defined in:
io.crio/encoding.cr:5
io/encoding.cr:28
io/error.cr
Constant Summary
-
DEFAULT_BUFFER_SIZE =
32768 -
Default size used for generic stream buffers.
Class Method Summary
-
.copy(src : IO, dst : IO, limit : Int) : Int64
Copy at mostlimit bytes fromsrc todst.
-
.copy(src : IO, dst : IO) : Int64
Copy all contents fromsrc todst.
-
.pipe(read_blocking : Bool | Nil = nil, write_blocking : Bool | Nil = nil) : Tuple(IO::FileDescriptor, IO::FileDescriptor)
Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element
Tuple. -
.pipe(read_blocking = nil, write_blocking = nil, &)
Creates a pair of pipe endpoints (connected to each other) and passes them to the given block.
-
.same_content?(stream1 : IO, stream2 : IO) : Bool
Compares two streamsstream1 tostream2 to determine if they are identical.
Instance Method Summary
-
#<<(obj : _) : self
Writes the given object into this
IO. -
#close
Closes this
IO. -
#closed? : Bool
Returns
trueif thisIOis closed. - #each_byte(&) : Nil
- #each_byte
- #each_char(&) : Nil
- #each_char
- #each_line(*args, **options, &block : String -> ) : Nil
- #each_line(*args, **options)
-
#encoding : String
Returns this
IO's encoding. -
#flush
Flushes buffered data, if any.
- #getb_to_end : Bytes
-
#gets(delimiter : Char, limit : Int, chomp = false) : String | Nil
Reads untildelimiter is found,limit bytes are read, or the end of the
IOis reached. -
#gets(chomp : Bool = true) : String | Nil
Reads a line from this
IO. -
#gets(limit : Int, chomp : Bool = false) : String | Nil
Reads a line of at mostlimit bytes from this
IO. -
#gets(delimiter : Char, chomp : Bool = false) : String | Nil
Reads untildelimiter is found, or the end of the
IOis reached. -
#gets(delimiter : String, chomp = false) : String | Nil
Reads untildelimiter is found or the end of the
IOis reached. - #gets_to_end : String
-
#peek : Bytes | Nil
Peeks into this IO, if possible.
-
#pos
Returns the current position (in bytes) in this
IO. -
#pos=(value)
Sets the current position (in bytes) in this
IO. -
#print(obj : _) : Nil
Same as
<<. -
#print(*objects : _) : Nil
Writes the given objects into this
IOby invokingto_s(io)on each of the objects. -
#printf(format_string : String, args : Array | Tuple) : Nil
Writes a formatted string to this IO.
-
#printf(format_string : String, *args) : Nil
Writes a formatted string to this IO.
-
#puts(string : String) : Nil
Writesstring to this
IO, followed by a newline character unless the string already ends with one. -
#puts(obj : _) : Nil
Writesobj to this
IO, followed by a newline character. -
#puts : Nil
Writes a newline character.
- #puts(*objects : _) : Nil
-
#read(slice : Bytes)
Reads at mostslice.size bytes from this
IOintoslice. -
#read_at(offset, bytesize, & : IO -> )
Yields an
IOto read a section inside this IO. -
#read_byte : UInt8 | Nil
Reads a single byte from this
IO. -
#read_bytes(type, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)
Reads an instance of the giventype from this
IOusing the specifiedformat. - #read_char : Char | Nil
-
#read_fully(slice : Bytes) : Int32
Tries to read exactly
slice.sizebytes from thisIOintoslice. -
#read_fully?(slice : Bytes) : Int32 | Nil
Tries to read exactly
slice.sizebytes from thisIOintoslice. -
#read_greedy(slice : Bytes) : Int32
Similar to
#read, but with the additional guarantee that either the buffer will be entirely filled or the EOF will be reached while trying. - #read_line(*args, **options) : String
-
#read_string(bytesize : Int) : String
Reads an UTF-8 encoded string of exactlybytesize bytes.
-
#read_utf8(slice : Bytes) : Int32
Reads UTF-8 decoded bytes into the givenslice.
-
#read_utf8_byte : UInt8 | Nil
Reads a single decoded UTF-8 byte from this
IO. -
#rewind
Rewinds this
IO. -
#seek(offset, whence : Seek = Seek::Set)
Seeks to a givenoffset (in bytes) according to thewhence argument.
-
#set_encoding(encoding : String, invalid : Symbol | Nil = nil) : Nil
Sets the encoding of this
IO. -
#skip(bytes_count : Int) : Nil
Reads and discards exactlybytes_count bytes.
-
#skip_to_end : Nil
Reads and discards bytes from
selfuntil there are no more bytes. -
#tell
Same as
#pos. -
#tty? : Bool
Returns
trueif thisIOis associated with a terminal device (tty),falseotherwise. -
#write(slice : Bytes) : Nil
Writes the contents ofslice into this
IO. -
#write_byte(byte : UInt8) : Nil
Writes a single byte into this
IO. -
#write_bytes(object : _, format : IO::ByteFormat = IO::ByteFormat::SystemEndian) : Nil
Writes the given object to this
IOusing the specifiedformat. -
#write_string(slice : Bytes) : Nil
Writes the contents ofslice, interpreted as a sequence of UTF-8 or ASCII characters, into this
IO. -
#write_utf8(slice : Bytes) : Nil
Writes the contents ofslice, interpreted as a sequence of UTF-8 or ASCII characters, into this
IO.DEPRECATED Use
#write_stringinstead.
Instance methods inherited from class Reference
==(other : self)==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s
Constructor methods inherited from class Reference
new
new,
unsafe_construct(address : Pointer, *args, **opts) : self
unsafe_construct
Class methods inherited from class Reference
pre_initialize(address : Pointer)
pre_initialize
Instance methods inherited from class Object
! : Bool
!,
!=(other)
!=,
!~(other)
!~,
==(other)
==,
===(other : JSON::Any)===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as
Class methods inherited from class Object
from_json(string_or_io : String | IO, root : String)from_json(string_or_io : String | IO) from_json, from_yaml(string_or_io : String | IO) from_yaml
Macros inherited from class Object
class_getter(*names, &block)
class_getter,
class_getter!(*names)
class_getter!,
class_getter?(*names, &block)
class_getter?,
class_property(*names, &block)
class_property,
class_property!(*names)
class_property!,
class_property?(*names, &block)
class_property?,
class_setter(*names)
class_setter,
def_clone
def_clone,
def_equals(*fields)
def_equals,
def_equals_and_hash(*fields)
def_equals_and_hash,
def_hash(*fields)
def_hash,
delegate(*methods, to object)
delegate,
forward_missing_to(delegate)
forward_missing_to,
getter(*names, &block)
getter,
getter!(*names)
getter!,
getter?(*names, &block)
getter?,
property(*names, &block)
property,
property!(*names)
property!,
property?(*names, &block)
property?,
setter(*names)
setter
Class Method Detail
Copy at mostlimit bytes fromsrc todst.
io = IO::Memory.new "hello"
io2 = IO::Memory.new
IO.copy io, io2, 3
io2.to_s # => "hel"
Copy all contents fromsrc todst.
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-elementTuple.
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 streamsstream1 tostream2 to determine if they are identical.
Returnstrue 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
Instance Method Detail
Writes the given object into thisIO.
This ends up callingto_s(io) on the object.
io = IO::Memory.new
io << 1
io << '-'
io << "Crystal"
io.to_s # => "1-Crystal"
Invokes the given block with each byte (UInt8) in thisIO.
io = IO::Memory.new("aあ")
io.each_byte do |byte|
puts byte
end
Output:
97
227
129
130
Returns anIterator for the bytes in thisIO.
io = IO::Memory.new("aあ")
iter = io.each_byte
iter.next # => 97
iter.next # => 227
iter.next # => 129
iter.next # => 130
Invokes the given block with eachChar in thisIO.
io = IO::Memory.new("あめ")
io.each_char do |char|
puts char
end
Output:
あ
め
Returns anIterator for the chars in thisIO.
io = IO::Memory.new("あめ")
iter = io.each_char
iter.next # => 'あ'
iter.next # => 'め'
Invokes the given block with eachline in thisIO, where a line
is defined by the arguments passed to this method, which can be the same
ones as in the#gets methods.
io = IO::Memory.new("hello\nworld")
io.each_line do |line|
puts line
end
# output:
# hello
# world
Returns anIterator for thelines in thisIO, where a line
is defined by the arguments passed to this method, which can be the same
ones as in the#gets methods.
io = IO::Memory.new("hello\nworld")
iter = io.each_line
iter.next # => "hello"
iter.next # => "world"
Flushes buffered data, if any.
IO defines this is a no-op method, but including types may override.
Reads the rest of thisIO data as a writableBytes.
io = IO::Memory.new Bytes[0, 1, 3, 6, 10, 15]
io.getb_to_end # => Bytes[0, 1, 3, 6, 10, 15]
io.getb_to_end # => Bytes[]
Reads untildelimiter is found,limit bytes are read, or the end of theIO is reached.
Returnsnil if called at the end of thisIO.
io = IO::Memory.new "hello\nworld"
io.gets('o', 3) # => "hel"
io.gets('r', 10) # => "lo\nwor"
io.gets('z', 10) # => "ld"
io.gets('w', 10) # => nil
Reads a line from thisIO. A line is terminated by the\n character.
Returnsnil if called at the end of thisIO.
By default the newline is removed from the returned string,
unlesschomp isfalse.
io = IO::Memory.new "hello\nworld\nfoo\n"
io.gets # => "hello"
io.gets(chomp: false) # => "world\n"
io.gets # => "foo"
io.gets # => nil
Reads a line of at mostlimit bytes from thisIO.
A line is terminated by the\n character.
Returnsnil if called at the end of thisIO.
io = IO::Memory.new "hello\nworld"
io.gets(3) # => "hel"
io.gets(3) # => "lo\n"
io.gets(3) # => "wor"
io.gets(3) # => "ld"
io.gets(3) # => nil
Reads untildelimiter is found, or the end of theIO is reached.
Returnsnil if called at the end of thisIO.
io = IO::Memory.new "hello\nworld"
io.gets('o') # => "hello"
io.gets('r') # => "\nwor"
io.gets('z') # => "ld"
io.gets('w') # => nil
Reads untildelimiter is found or the end of theIO is reached.
Returnsnil if called at the end of thisIO.
io = IO::Memory.new "hello\nworld"
io.gets("wo") # => "hello\nwo"
io.gets("wo") # => "rld"
io.gets("wo") # => nil
Reads the rest of thisIO data as aString.
io = IO::Memory.new "hello world"
io.gets_to_end # => "hello world"
io.gets_to_end # => ""
Peeks into this IO, if possible.
It returns:
nilif this IO isn't peekable at this moment or at all- 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 returnsnil, but IO implementations
that provide buffering or wrap other IOs should override
this method.
Returns the current position (in bytes) in thisIO.
TheIO class raises on this method, but some subclasses, notable
IO::FileDescriptor andIO::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 thisIO.
TheIO class raises on this method, but some subclasses, notable
IO::FileDescriptor andIO::Memory implement it.
File.write("testfile", "hello")
file = File.new("testfile")
file.pos = 3
file.gets_to_end # => "lo"
Same as<<.
io = IO::Memory.new
io.print 1
io.print '-'
io.print "Crystal"
io.to_s # => "1-Crystal"
Writes the given objects into thisIO by invokingto_s(io)
on each of the objects.
io = IO::Memory.new
io.print 1, '-', "Crystal"
io.to_s # => "1-Crystal"
Writes a formatted string to this IO.
For details on the format string, see top-level::printf.
Writes a formatted string to this IO.
For details on the format string, see top-level::printf.
Writesstring to thisIO, 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"
Writesobj to thisIO, followed by a newline character.
io = IO::Memory.new
io.puts 1
io.puts "Crystal"
io.to_s # => "1\nCrystal\n"
Writesobjects to thisIO, each followed by a newline character unless
the object is aString and already ends with a newline.
io = IO::Memory.new
io.puts 1, '-', "Crystal"
io.to_s # => "1\n-\nCrystal\n"
Reads at mostslice.size bytes from thisIO intoslice.
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 anIO to read a section inside this IO.
TheIO class raises on this method, but some subclasses, notable
File andIO::Memory implement it.
Multiple sections can be read concurrently.
Reads a single byte from thisIO. Returnsnil 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 giventype from thisIO using the specifiedformat.
This ends up invokingtype.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.
SeeInt.from_io andFloat.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
Reads a singleChar from thisIO. Returnsnil if there is no
more data to read.
io = IO::Memory.new "あ"
io.read_char # => 'あ'
io.read_char # => nil
Tries to read exactlyslice.size bytes from thisIO intoslice.
RaisesEOFError if there aren'tslice.size bytes of data.
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) # raises IO::EOFError
#read_greedy also tries to fill the entire buffer if possible,
but still allows the partially filled slice to be used if an early EOF was reached.
Tries to read exactlyslice.size bytes from thisIO intoslice.
Returnsnil if there aren'tslice.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
#read_greedy also tries to fill the entire buffer if possible,
but still allows the partially filled slice to be used if an early EOF was reached.
Similar to#read, but with the additional guarantee that either
the buffer will be entirely filled or the EOF will be reached while trying.
Calling this method may result in multiple calls to#read if necessary.
io = IO::Memory.new "123451234"
slice = Bytes.new(5)
io.read_greedy(slice) # => 5
slice # => Bytes[49, 50, 51, 52, 53]
io.read_greedy(slice) # => 4
#read_fully and#read_fully? also try to fill the entire buffer but error on unexpected EOF.
Reads an UTF-8 encoded string of exactlybytesize bytes.
RaisesEOFError 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 givenslice. 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 thisIO.
Returnsnil 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]
Seeks to a givenoffset (in bytes) according to thewhence argument.
TheIO class raises on this method, but some subclasses, notable
IO::FileDescriptor andIO::Memory implement it.
Returnsself.
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 thisIO.
Theinvalid 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.
Reads and discards exactlybytes_count bytes.
RaisesIO::EOFError if there aren't at leastbytes_count bytes.
io = IO::Memory.new "hello world"
io.skip(6)
io.gets # => "world"
io.skip(1) # raises IO::EOFError
Returnstrue if thisIO is associated with a terminal device (tty),false otherwise.
IO returnsfalse, but including types may override.
STDIN.tty? # => true
IO::Memory.new.tty? # => false
Writes the contents ofslice into thisIO.
io = IO::Memory.new
slice = Bytes.new(4) { |i| ('a'.ord + i).to_u8 }
io.write(slice)
io.to_s # => "abcd"
Writes the given object to thisIO using the specifiedformat.
This ends up invokingobject.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.
SeeInt#to_io andFloat#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 the contents ofslice, interpreted as a sequence of UTF-8 or ASCII
characters, into thisIO. The contents are transcoded into thisIO's
current encoding.
bytes = "你".to_slice # => Bytes[228, 189, 160]
io = IO::Memory.new
io.set_encoding("GB2312")
io.write_string(bytes)
io.to_slice # => Bytes[196, 227]
"你".encode("GB2312") # => Bytes[196, 227]
Writes the contents ofslice, interpreted as a sequence of UTF-8 or ASCII
characters, into thisIO. The contents are transcoded into thisIO's
current encoding.
bytes = "你".to_slice # => Bytes[228, 189, 160]
io = IO::Memory.new
io.set_encoding("GB2312")
io.write_string(bytes)
io.to_slice # => Bytes[196, 227]
"你".encode("GB2312") # => Bytes[196, 227]
DEPRECATED Use#write_string instead.