# abstract class IO

- IO
- Reference
- Object

##
Overview

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 IO

For 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"

###
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`, `#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.cr
io/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 most limit bytes from src to dst.

- .copy(src : IO, dst : IO) : Int64

  Copy all contents from src to dst.

- .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 streams stream1 to stream2 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 `true` if this `IO` is closed.

- #each_byte(&) : Nil

  Invokes the given block with each byte (`UInt8`) in this `IO`.

- #each_byte

  Returns an `Iterator` for the bytes in this `IO`.

- #each_char(&) : Nil

  Invokes the given block with each `Char` in this `IO`.

- #each_char

  Returns an `Iterator` for the chars in this `IO`.

- #each_line(*args, **options, &block : String -> ) : Nil

  Invokes the given block with each line in this `IO`, where a line is defined by the arguments passed to this method, which can be the same ones as in the `#gets` methods.

- #each_line(*args, **options)

  Returns an `Iterator` for the lines in this `IO`, where a line is defined by the arguments passed to this method, which can be the same ones as in the `#gets` methods.

- #encoding : String

  Returns this `IO`'s encoding.

- #flush

  Flushes buffered data, if any.

- #getb_to_end : Bytes

  Reads the rest of this `IO` data as a writable `Bytes`.

- #gets(delimiter : Char, limit : Int, chomp = false) : String | Nil

  Reads until delimiter is found, limit bytes are read, or the end of the `IO` is 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 most limit bytes from this `IO`.

- #gets(delimiter : Char, chomp : Bool = false) : String | Nil

  Reads until delimiter is found, or the end of the `IO` is reached.

- #gets(delimiter : String, chomp = false) : String | Nil

  Reads until delimiter is found or the end of the `IO` is reached.

- #gets_to_end : String

  Reads the rest of this `IO` data as a `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 `IO` by invoking `to_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

  Writes string to this `IO`, followed by a newline character unless the string already ends with one.

- #puts(obj : _) : Nil

  Writes obj to this `IO`, followed by a newline character.

- #puts : Nil

  Writes a newline character.

- #puts(*objects : _) : Nil

  Writes objects to this `IO`, each followed by a newline character unless the object is a `String` and already ends with a newline.

- #read(slice : Bytes)

  Reads at most slice.size bytes from this `IO` into slice.

- #read_at(offset, bytesize, & : IO -> )

  Yields an `IO` to 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 given type from this `IO` using the specified format.

- #read_char : Char | Nil

  Reads a single `Char` from this `IO`.

- #read_fully(slice : Bytes) : Int32

  Tries to read exactly `slice.size` bytes from this `IO` into slice.

- #read_fully?(slice : Bytes) : Int32 | Nil

  Tries to read exactly `slice.size` bytes from this `IO` into slice.

- #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

  Same as `#gets`, but raises `EOFError` if called at the end of this `IO`.

- #read_string(bytesize : Int) : String

  Reads an UTF-8 encoded string of exactly bytesize bytes.

- #read_utf8(slice : Bytes) : Int32

  Reads UTF-8 decoded bytes into the given slice.

- #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 given offset (in bytes) according to the whence argument.

- #set_encoding(encoding : String, invalid : Symbol | Nil = nil) : 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.

- #tell

  Same as `#pos`.

- #tty? : Bool

  Returns `true` if this `IO` 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) : Nil

  Writes a single byte into this `IO`.

- #write_bytes(object : _, format : IO::ByteFormat = IO::ByteFormat::SystemEndian) : Nil

  Writes the given object to this `IO` using the specified format.

- #write_string(slice : Bytes) : Nil

  Writes the contents of slice, interpreted as a sequence of UTF-8 or ASCII characters, into this `IO`.

- #write_utf8(slice : Bytes) : Nil

  Writes the contents of slice, interpreted as a sequence of UTF-8 or ASCII characters, into this `IO`.

  DEPRECATED Use `#write_string` instead.

### 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

def self.copy(src : IO, dst : IO, limit : Int) : Int64 #

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 : IO, dst : IO) : Int64 #

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 : 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`.

    reader, writer = IO.pipe
    writer.puts "hello"
    writer.puts "world"
    reader.gets # => "hello"
    reader.gets # => "world"

def self.pipe(read_blocking = nil, write_blocking = nil, &) #

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.same_content?(stream1 : IO, stream2 : IO) : Bool #

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

##
Instance Method Detail

def <<(obj : _) : self #

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 close #

Closes this `IO`.

`IO` defines this is a no-op method, but including types may override.

def closed? : Bool #

Returns `true` if this `IO` is closed.

`IO` defines returns `false`, but including types may override.

def each_byte(&) : Nil #

Invokes the given block with each byte (`UInt8`) in this `IO`.

    io = IO::Memory.new("aあ")
    io.each_byte do |byte|
      puts byte
    end

Output:

    97
    227
    129
    130

def each_byte #

Returns an `Iterator` for the bytes in this `IO`.

    io = IO::Memory.new("aあ")
    iter = io.each_byte
    iter.next # => 97
    iter.next # => 227
    iter.next # => 129
    iter.next # => 130

def each_char(&) : Nil #

Invokes the given block with each `Char` in this `IO`.

    io = IO::Memory.new("あめ")
    io.each_char do |char|
      puts char
    end

Output:

    あ
    め

def each_char #

Returns an `Iterator` for the chars in this `IO`.

    io = IO::Memory.new("あめ")
    iter = io.each_char
    iter.next # => 'あ'
    iter.next # => 'め'

def each_line(*args, **options, &block : String -> ) : Nil #

Invokes the given block with each line in this `IO`, 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

def each_line(*args, **options) #

Returns an `Iterator` for the lines in this `IO`, 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"

def encoding : String #

Returns this `IO`'s encoding. The default is `UTF-8`.

def flush #

Flushes buffered data, if any.

`IO` defines this is a no-op method, but including types may override.

def getb_to_end : Bytes #

Reads the rest of this `IO` data as a writable `Bytes`.

    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[]

def gets(delimiter : Char, limit : Int, chomp = false) : String | Nil #

Reads until delimiter is found, limit bytes are read, or the end of the `IO` is reached. Returns `nil` if called at the end of this `IO`.

    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

def gets(chomp : Bool = true) : String | Nil #

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 gets(limit : Int, chomp : Bool = false) : String | Nil #

Reads a line of at most limit bytes from this `IO`. A line is terminated by the `\n` character. Returns `nil` if called at the end of this `IO`.

    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

def gets(delimiter : Char, chomp : Bool = false) : String | Nil #

Reads until delimiter is found, or the end of the `IO` is reached. Returns `nil` if called at the end of this `IO`.

    io = IO::Memory.new "hello\nworld"
    io.gets('o') # => "hello"
    io.gets('r') # => "\nwor"
    io.gets('z') # => "ld"
    io.gets('w') # => nil

def gets(delimiter : String, chomp = false) : String | Nil #

Reads until delimiter is found or the end of the `IO` is reached. Returns `nil` if called at the end of this `IO`.

    io = IO::Memory.new "hello\nworld"
    io.gets("wo") # => "hello\nwo"
    io.gets("wo") # => "rld"
    io.gets("wo") # => nil

def gets_to_end : String #

Reads the rest of this `IO` data as a `String`.

    io = IO::Memory.new "hello world"
    io.gets_to_end # => "hello world"
    io.gets_to_end # => ""

def peek : Bytes | Nil #

Peeks into this IO, if possible.

It returns:

- `nil` if 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 returns `nil`, but IO implementations that provide buffering or wrap other IOs should override this method.

def pos #

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

def pos=(value) #

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"

def print(obj : _) : Nil #

Same as `<<`.

    io = IO::Memory.new
    io.print 1
    io.print '-'
    io.print "Crystal"
    io.to_s # => "1-Crystal"

def print(*objects : _) : Nil #

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 printf(format_string : String, args : Array | Tuple) : Nil #

Writes a formatted string to this IO. For details on the format string, see top-level `::printf`.

def printf(format_string : String, *args) : Nil #

Writes a formatted string to this IO. For details on the format string, see top-level `::printf`.

def puts(string : String) : Nil #

Writes 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"

def puts(obj : _) : Nil #

Writes obj 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 : Nil #

Writes a newline character.

    io = IO::Memory.new
    io.puts
    io.to_s # => "\n"

def puts(*objects : _) : Nil #

Writes objects to this `IO`, each followed by a newline character unless the object is a `String` and already ends with a newline.

    io = IO::Memory.new
    io.puts 1, '-', "Crystal"
    io.to_s # => "1\n-\nCrystal\n"

abstract def read(slice : Bytes) #

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

def read_at(offset, bytesize, & : IO -> ) #

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.

def read_byte : UInt8 | Nil #

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) #

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_char : Char | Nil #

Reads a single `Char` from this `IO`. Returns `nil` if there is no more data to read.

    io = IO::Memory.new "あ"
    io.read_char # => 'あ'
    io.read_char # => nil

def read_fully(slice : Bytes) : Int32 #

Tries to read exactly `slice.size` bytes from this `IO` into slice. Raises `EOFError` if there aren't `slice.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.

def read_fully?(slice : Bytes) : Int32 | Nil #

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

`#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.

def 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.

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.

def read_line(*args, **options) : String #

Same as `#gets`, but raises `EOFError` if called at the end of this `IO`.

def read_string(bytesize : Int) : String #

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) : Int32 #

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_byte : UInt8 | Nil #

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 rewind #

Rewinds this `IO`. By default this method raises, but including types may implement it.

def seek(offset, whence : Seek = Seek::Set) #

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"

def set_encoding(encoding : String, invalid : Symbol | Nil = nil) : Nil #

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) : Nil #

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 skip_to_end : Nil #

Reads and discards bytes from `self` until there are no more bytes.

def tell #

Same as `#pos`.

def tty? : Bool #

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) : Nil #

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) : Nil #

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) : Nil #

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_string(slice : Bytes) : Nil #

Writes the contents of slice, interpreted as a sequence of UTF-8 or ASCII characters, into this `IO`. The contents are transcoded into this `IO`'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]

def write_utf8(slice : Bytes) : Nil #

Writes the contents of slice, interpreted as a sequence of UTF-8 or ASCII characters, into this `IO`. The contents are transcoded into this `IO`'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.