class IO

Parent:
Object
Included modules:
File::Constants, Enumerable

An instance of class IO (commonly called a stream) represents an input/output stream in the underlying operating system. Class IO is the basis for input and output in Ruby.

Class File is the only class in the Ruby core that is a subclass of IO. Some classes in the Ruby standard library are also subclasses of IO; these include TCPSocket and UDPSocket.

The global constant ARGF (also accessible as $<) provides an IO-like stream that allows access to all file paths found in ARGV (or found in STDIN if ARGV is empty). ARGF is not itself a subclass of IO.

Class StringIO provides an IO-like stream that handles a String. StringIO is not itself a subclass of IO.

Important objects based on IO include:

  • $stdin.

  • $stdout.

  • $stderr.

  • Instances of class File.

An instance of IO may be created using:

  • IO.new: returns a new IO object for the given integer file descriptor.

  • IO.open: passes a new IO object to the given block.

  • IO.popen: returns a new IO object that is connected to the $stdin and $stdout of a newly-launched subprocess.

  • Kernel#open: Returns a new IO object connected to a given source: stream, file, or subprocess.

Like a File stream, an IO stream has:

  • A read/write mode, which may be read-only, write-only, or read/write; see Read/Write Mode.

  • A data mode, which may be text-only or binary; see Data Mode.

  • Internal and external encodings; see Encodings.

And like other IO streams, it has:

  • A position, which determines where in the stream the next read or write is to occur; see Position.

  • A line number, which is a special, line-oriented, “position” (different from the position mentioned above); see Line Number.

Extension io/console

Extension io/console provides numerous methods for interacting with the console; requiring it adds numerous methods to class IO.

Example Files

Many examples here use these variables:

# English text with newlines.
text = <<~EOT
  First line
  Second line

  Fourth line
  Fifth line
EOT

# Russian text.
russian = "\u{442 435 441 442}" # => "тест"

# Binary data.
data = "\u9990\u9991\u9992\u9993\u9994"

# Text file.
File.write('t.txt', text)

# File with Russian text.
File.write('t.rus', russian)

# File with binary data.
f = File.new('t.dat', 'wb:UTF-16')
f.write(data)
f.close

Open Options

A number of IO methods accept optional keyword arguments that determine how a new stream is to be opened:

  • :mode: Stream mode.

  • :flags: Integer file open flags; If mode is also given, the two are bitwise-ORed.

  • :external_encoding: External encoding for the stream.

  • :internal_encoding: Internal encoding for the stream. '-' is a synonym for the default internal encoding. If the value is nil no conversion occurs.

  • :encoding: Specifies external and internal encodings as 'extern:intern'.

  • :textmode: If a truthy value, specifies the mode as text-only, binary otherwise.

  • :binmode: If a truthy value, specifies the mode as binary, text-only otherwise.

  • :autoclose: If a truthy value, specifies that the fd will close when the stream closes; otherwise it remains open.

  • :path: If a string value is provided, it is used in inspect and is available as path method.

Also available are the options offered in String#encode, which may control conversion between external and internal encoding.

Basic IO

You can perform basic stream IO with these methods, which typically operate on multi-byte strings:

  • IO#read: Reads and returns some or all of the remaining bytes from the stream.

  • IO#write: Writes zero or more strings to the stream; each given object that is not already a string is converted via to_s.

Position

An IO stream has a nonnegative integer position, which is the byte offset at which the next read or write is to occur. A new stream has position zero (and line number zero); method rewind resets the position (and line number) to zero.

These methods discard buffers and the Encoding::Converter instances used for that IO.

The relevant methods:

  • IO#tell (aliased as pos): Returns the current position (in bytes) in the stream.

  • IO#pos=: Sets the position of the stream to a given integer new_position (in bytes).

  • IO#seek: Sets the position of the stream to a given integer offset (in bytes), relative to a given position whence (indicating the beginning, end, or current position).

  • IO#rewind: Positions the stream at the beginning (also resetting the line number).

Open and Closed Streams

A new IO stream may be open for reading, open for writing, or both.

A stream is automatically closed when claimed by the garbage collector.

Attempted reading or writing on a closed stream raises an exception.

The relevant methods:

End-of-Stream

You can query whether a stream is positioned at its end:

  • IO#eof? (also aliased as eof): Returns whether the stream is at end-of-stream.

You can reposition to end-of-stream by using method IO#seek:

f = File.new('t.txt')
f.eof? # => false
f.seek(0, :END)
f.eof? # => true
f.close

Or by reading all stream content (which is slower than using IO#seek):

f.rewind
f.eof? # => false
f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
f.eof? # => true

Line IO

Class IO supports line-oriented input and output

Line Input

Class IO supports line-oriented input for files and IO streams

File Line Input

You can read lines from a file using these methods:

  • IO.foreach: Reads each line and passes it to the given block.

  • IO.readlines: Reads and returns all lines in an array.

For each of these methods:

  • You can specify open options.

  • Line parsing depends on the effective line separator; see Line Separator.

  • The length of each returned line depends on the effective line limit; see Line Limit.

Stream Line Input

You can read lines from an IO stream using these methods:

For each of these methods:

  • Reading may begin mid-line, depending on the stream’s position; see Position.

  • Line parsing depends on the effective line separator; see Line Separator.

  • The length of each returned line depends on the effective line limit; see Line Limit.

Line Separator

Each of the line input methods uses a line separator: the string that determines what is considered a line; it is sometimes called the input record separator.

The default line separator is taken from global variable $/, whose initial value is "\n".

Generally, the line to be read next is all data from the current position to the next line separator (but see Special Line Separator Values):

f = File.new('t.txt')
# Method gets with no sep argument returns the next line, according to $/.
f.gets # => "First line\n"
f.gets # => "Second line\n"
f.gets # => "\n"
f.gets # => "Fourth line\n"
f.gets # => "Fifth line\n"
f.close

You can use a different line separator by passing argument sep:

f = File.new('t.txt')
f.gets('l')   # => "First l"
f.gets('li')  # => "ine\nSecond li"
f.gets('lin') # => "ne\n\nFourth lin"
f.gets        # => "e\n"
f.close

Or by setting global variable $/:

f = File.new('t.txt')
$/ = 'l'
f.gets # => "First l"
f.gets # => "ine\nSecond l"
f.gets # => "ine\n\nFourth l"
f.close
Special Line Separator Values

Each of the line input methods accepts two special values for parameter sep:

  • nil: The entire stream is to be read (“slurped”) into a single string:

    f = File.new('t.txt')
    f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
    f.close
    
  • '' (the empty string): The next “paragraph” is to be read (paragraphs being separated by two consecutive line separators):

    f = File.new('t.txt')
    f.gets('') # => "First line\nSecond line\n\n"
    f.gets('') # => "Fourth line\nFifth line\n"
    f.close
    
Line Limit

Each of the line input methods uses an integer line limit, which restricts the number of bytes that may be returned. (A multi-byte character will not be split, and so a returned line may be slightly longer than the limit).

The default limit value is -1; any negative limit value means that there is no limit.

If there is no limit, the line is determined only by sep.

# Text with 1-byte characters.
File.open('t.txt') {|f| f.gets(1) }  # => "F"
File.open('t.txt') {|f| f.gets(2) }  # => "Fi"
File.open('t.txt') {|f| f.gets(3) }  # => "Fir"
File.open('t.txt') {|f| f.gets(4) }  # => "Firs"
# No more than one line.
File.open('t.txt') {|f| f.gets(10) } # => "First line"
File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
File.open('t.txt') {|f| f.gets(12) } # => "First line\n"

# Text with 2-byte characters, which will not be split.
File.open('t.rus') {|f| f.gets(1).size } # => 1
File.open('t.rus') {|f| f.gets(2).size } # => 1
File.open('t.rus') {|f| f.gets(3).size } # => 2
File.open('t.rus') {|f| f.gets(4).size } # => 2
Line Separator and Line Limit

With arguments sep and limit given, combines the two behaviors:

  • Returns the next line as determined by line separator sep.

  • But returns no more bytes than are allowed by the limit limit.

Example:

File.open('t.txt') {|f| f.gets('li', 20) } # => "First li"
File.open('t.txt') {|f| f.gets('li', 2) }  # => "Fi"
Line Number

A readable IO stream has a non-negative integer line number:

Unless modified by a call to method IO#lineno=, the line number is the number of lines read by certain line-oriented methods, according to the effective line separator:

  • IO.foreach: Increments the line number on each call to the block.

  • IO#each_line: Increments the line number on each call to the block.

  • IO#gets: Increments the line number.

  • IO#readline: Increments the line number.

  • IO#readlines: Increments the line number for each line read.

A new stream is initially has line number zero (and position zero); method rewind resets the line number (and position) to zero:

f = File.new('t.txt')
f.lineno # => 0
f.gets   # => "First line\n"
f.lineno # => 1
f.rewind
f.lineno # => 0
f.close

Reading lines from a stream usually changes its line number:

f = File.new('t.txt', 'r')
f.lineno   # => 0
f.readline # => "This is line one.\n"
f.lineno   # => 1
f.readline # => "This is the second line.\n"
f.lineno   # => 2
f.readline # => "Here's the third line.\n"
f.lineno   # => 3
f.eof?     # => true
f.close

Iterating over lines in a stream usually changes its line number:

File.open('t.txt') do |f|
  f.each_line do |line|
    p "position=#{f.pos} eof?=#{f.eof?} lineno=#{f.lineno}"
  end
end

Output:

"position=11 eof?=false lineno=1"
"position=23 eof?=false lineno=2"
"position=24 eof?=false lineno=3"
"position=36 eof?=false lineno=4"
"position=47 eof?=true lineno=5"

Unlike the stream’s position, the line number does not affect where the next read or write will occur:

f = File.new('t.txt')
f.lineno = 1000
f.lineno # => 1000
f.gets   # => "First line\n"
f.lineno # => 1001
f.close

Associated with the line number is the global variable $.:

  • When a stream is opened, $. is not set; its value is left over from previous activity in the process:

    $. = 41
    f = File.new('t.txt')
    $. = 41
    # => 41
    f.close
    
  • When a stream is read, $. is set to the line number for that stream:

    f0 = File.new('t.txt')
    f1 = File.new('t.dat')
    f0.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
    $.           # => 5
    f1.readlines # => ["\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94"]
    $.           # => 1
    f0.close
    f1.close
    
  • Methods IO#rewind and IO#seek do not affect $.:

    f = File.new('t.txt')
    f.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
    $.          # => 5
    f.rewind
    f.seek(0, :SET)
    $.          # => 5
    f.close
    

Line Output

You can write to an IO stream line-by-line using this method:

  • IO#puts: Writes objects to the stream.

Character IO

You can process an IO stream character-by-character using these methods:

  • IO#getc: Reads and returns the next character from the stream.

  • IO#readchar: Like getc, but raises an exception at end-of-stream.

  • IO#ungetc: Pushes back (“unshifts”) a character or integer onto the stream.

  • IO#putc: Writes a character to the stream.

  • IO#each_char: Reads each remaining character in the stream, passing the character to the given block.

Byte IO

You can process an IO stream byte-by-byte using these methods:

  • IO#getbyte: Returns the next 8-bit byte as an integer in range 0..255.

  • IO#readbyte: Like getbyte, but raises an exception if at end-of-stream.

  • IO#ungetbyte: Pushes back (“unshifts”) a byte back onto the stream.

  • IO#each_byte: Reads each remaining byte in the stream, passing the byte to the given block.

Codepoint IO

You can process an IO stream codepoint-by-codepoint:

What’s Here

First, what’s elsewhere. Class IO:

Here, class IO provides methods that are useful for:

Creating

  • ::new (aliased as ::for_fd): Creates and returns a new IO object for the given integer file descriptor.

  • ::open: Creates a new IO object.

  • ::pipe: Creates a connected pair of reader and writer IO objects.

  • ::popen: Creates an IO object to interact with a subprocess.

  • ::select: Selects which given IO instances are ready for reading, writing, or have pending exceptions.

Reading

  • ::binread: Returns a binary string with all or a subset of bytes from the given file.

  • ::read: Returns a string with all or a subset of bytes from the given file.

  • ::readlines: Returns an array of strings, which are the lines from the given file.

  • getbyte: Returns the next 8-bit byte read from self as an integer.

  • getc: Returns the next character read from self as a string.

  • gets: Returns the line read from self.

  • pread: Returns all or the next n bytes read from self, not updating the receiver’s offset.

  • read: Returns all remaining or the next n bytes read from self for a given n.

  • read_nonblock: the next n bytes read from self for a given n, in non-block mode.

  • readbyte: Returns the next byte read from self; same as getbyte, but raises an exception on end-of-stream.

  • readchar: Returns the next character read from self; same as getc, but raises an exception on end-of-stream.

  • readline: Returns the next line read from self; same as getline, but raises an exception of end-of-stream.

  • readlines: Returns an array of all lines read read from self.

  • readpartial: Returns up to the given number of bytes from self.

Writing

  • ::binwrite: Writes the given string to the file at the given filepath, in binary mode.

  • ::write: Writes the given string to self.

  • <<: Appends the given string to self.

  • print: Prints last read line or given objects to self.

  • printf: Writes to self based on the given format string and objects.

  • putc: Writes a character to self.

  • puts: Writes lines to self, making sure line ends with a newline.

  • pwrite: Writes the given string at the given offset, not updating the receiver’s offset.

  • write: Writes one or more given strings to self.

  • write_nonblock: Writes one or more given strings to self in non-blocking mode.

Positioning

  • lineno: Returns the current line number in self.

  • lineno=: Sets the line number is self.

  • pos (aliased as tell): Returns the current byte offset in self.

  • pos=: Sets the byte offset in self.

  • reopen: Reassociates self with a new or existing IO stream.

  • rewind: Positions self to the beginning of input.

  • seek: Sets the offset for self relative to given position.

Iterating

  • ::foreach: Yields each line of given file to the block.

  • each (aliased as each_line): Calls the given block with each successive line in self.

  • each_byte: Calls the given block with each successive byte in self as an integer.

  • each_char: Calls the given block with each successive character in self as a string.

  • each_codepoint: Calls the given block with each successive codepoint in self as an integer.

Settings

Querying

  • autoclose?: Returns whether self auto-closes.

  • binmode?: Returns whether self is in binary mode.

  • close_on_exec?: Returns the close-on-exec flag for self.

  • closed?: Returns whether self is closed.

  • eof? (aliased as eof): Returns whether self is at end-of-stream.

  • external_encoding: Returns the external encoding object for self.

  • fileno (aliased as to_i): Returns the integer file descriptor for self

  • internal_encoding: Returns the internal encoding object for self.

  • pid: Returns the process ID of a child process associated with self, if self was created by ::popen.

  • stat: Returns the File::Stat object containing status information for self.

  • sync: Returns whether self is in sync-mode.

  • tty? (aliased as isatty): Returns whether self is a terminal.

Buffering

  • fdatasync: Immediately writes all buffered data in self to disk.

  • flush: Flushes any buffered data within self to the underlying operating system.

  • fsync: Immediately writes all buffered data and attributes in self to disk.

  • ungetbyte: Prepends buffer for self with given integer byte or string.

  • ungetc: Prepends buffer for self with given string.

Low-Level Access

  • ::sysopen: Opens the file given by its path, returning the integer file descriptor.

  • advise: Announces the intention to access data from self in a specific way.

  • fcntl: Passes a low-level command to the file specified by the given file descriptor.

  • ioctl: Passes a low-level command to the device specified by the given file descriptor.

  • sysread: Returns up to the next n bytes read from self using a low-level read.

  • sysseek: Sets the offset for self.

  • syswrite: Writes the given string to self using a low-level write.

Other

  • ::copy_stream: Copies data from a source to a destination, each of which is a filepath or an IO-like object.

  • ::try_convert: Returns a new IO object resulting from converting the given object.

  • inspect: Returns the string representation of self.

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.