Class: IO

Inherits:
Object show all
Includes:
Enumerable, File::Constants
Defined in:
io.c

Overview

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:

:include: doc/examples/files.rdoc

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:

  • IO#close: Closes the stream for both reading and writing.

  • IO#close_read: Closes the stream for reading.

  • IO#close_write: Closes the stream for writing.

  • IO#closed?: Returns whether the stream is closed.

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:

  • IO#each_line: Reads each remaining line, passing it to the given block.

  • IO#gets: Returns the next line.

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

  • IO#readlines: Returns all remaining lines in an array.

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:

  • IO#lineno: Returns the line number.

  • IO#lineno=: Resets and returns the 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:

  • IO#each_codepoint: Reads each remaining codepoint, passing it to the given block.

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

  • #autoclose=: Sets whether self auto-closes.

  • #binmode: Sets self to binary mode.

  • #close: Closes self.

  • #close_on_exec=: Sets the close-on-exec flag.

  • #close_read: Closes self for reading.

  • #close_write: Closes self for writing.

  • #set_encoding: Sets the encoding for self.

  • #set_encoding_by_bom: Sets the encoding for self, based on its Unicode byte-order-mark.

  • #sync=: Sets the sync-mode to the given value.

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.

Direct Known Subclasses

File

Defined Under Namespace

Modules: WaitReadable, WaitWritable Classes: Buffer, EAGAINWaitReadable, EAGAINWaitWritable, EINPROGRESSWaitReadable, EINPROGRESSWaitWritable, EWOULDBLOCKWaitReadable, EWOULDBLOCKWaitWritable, TimeoutError

Constant Summary collapse

READABLE =

Readable event mask for IO#wait.

INT2NUM(RUBY_IO_READABLE)
WRITABLE =

Writable event mask for IO#wait.

INT2NUM(RUBY_IO_WRITABLE)
PRIORITY =

Priority event mask for IO#wait.

INT2NUM(RUBY_IO_PRIORITY)
SEEK_SET =

Set I/O position from the beginning

INT2FIX(SEEK_SET)
SEEK_CUR =

Set I/O position from the current position

INT2FIX(SEEK_CUR)
SEEK_END =

Set I/O position from the end

INT2FIX(SEEK_END)
SEEK_DATA =

Set I/O position to the next location containing data

INT2FIX(SEEK_DATA)
SEEK_HOLE =

Set I/O position to the next hole

INT2FIX(SEEK_HOLE)

Constants included from File::Constants

File::Constants::APPEND, File::Constants::BINARY, File::Constants::CREAT, File::Constants::DIRECT, File::Constants::DSYNC, File::Constants::EXCL, File::Constants::LOCK_EX, File::Constants::LOCK_NB, File::Constants::LOCK_SH, File::Constants::LOCK_UN, File::Constants::NOATIME, File::Constants::NOCTTY, File::Constants::NOFOLLOW, File::Constants::NONBLOCK, File::Constants::NULL, File::Constants::RDONLY, File::Constants::RDWR, File::Constants::RSYNC, File::Constants::SHARE_DELETE, File::Constants::SYNC, File::Constants::TMPFILE, File::Constants::TRUNC, File::Constants::WRONLY

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#all?, #any?, #chain, #chunk, #chunk_while, #collect, #collect_concat, #compact, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #filter, #filter_map, #find, #find_all, #find_index, #first, #flat_map, #grep, #grep_v, #group_by, #include?, #inject, #lazy, #map, #max, #max_by, #member?, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reject, #reverse_each, #select, #slice_after, #slice_before, #slice_when, #sort, #sort_by, #sum, #take, #take_while, #tally, #to_a, #to_h, #uniq, #zip

Constructor Details

#new(fd, mode = 'r', **opts) ⇒ IO

Creates and returns a new IO object (file stream) from a file descriptor.

IO.new may be useful for interaction with low-level libraries. For higher-level interactions, it may be simpler to create the file stream using File.open.

Argument fd must be a valid file descriptor (integer):

path = 't.tmp'
fd = IO.sysopen(path) # => 3
IO.new(fd)            # => #<IO:fd 3>

The new IO object does not inherit encoding (because the integer file descriptor does not have an encoding):

fd = IO.sysopen('t.rus', 'rb')
io = IO.new(fd)
io.external_encoding # => #<Encoding:UTF-8> # Not ASCII-8BIT.

Optional argument mode (defaults to ‘r’) must specify a valid mode; see Access Modes:

IO.new(fd, 'w')         # => #<IO:fd 3>
IO.new(fd, File::WRONLY) # => #<IO:fd 3>

Optional keyword arguments opts specify:

Examples:

IO.new(fd, internal_encoding: nil) # => #<IO:fd 3>
IO.new(fd, autoclose: true)        # => #<IO:fd 3>


9493
9494
9495
9496
9497
9498
9499
9500
9501
# File 'io.c', line 9493

static VALUE
rb_io_initialize(int argc, VALUE *argv, VALUE io)
{
    VALUE fnum, vmode;
    VALUE opt;

    rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
    return io_initialize(io, fnum, vmode, opt);
}

Class Method Details

.binread(path, length = nil, offset = 0) ⇒ String?

Behaves like IO.read, except that the stream is opened in binary mode with ASCII-8BIT encoding.

When called from class IO (but not subclasses of IO), this method has potential security vulnerabilities if called with untrusted input; see Command Injection.

Returns:



12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
# File 'io.c', line 12282

static VALUE
rb_io_s_binread(int argc, VALUE *argv, VALUE io)
{
    VALUE offset;
    struct foreach_arg arg;
    enum {
        fmode = FMODE_READABLE|FMODE_BINMODE,
        oflags = O_RDONLY
#ifdef O_BINARY
                |O_BINARY
#endif
    };
    struct rb_io_encoding convconfig = {NULL, NULL, 0, Qnil};

    rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
    FilePathValue(argv[0]);
    convconfig.enc = rb_ascii8bit_encoding();
    arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
    if (NIL_P(arg.io)) return Qnil;
    arg.argv = argv+1;
    arg.argc = (argc > 1) ? 1 : 0;
    if (!NIL_P(offset)) {
        struct seek_arg sarg;
        int state = 0;
        sarg.io = arg.io;
        sarg.offset = offset;
        sarg.mode = SEEK_SET;
        rb_protect(seek_before_access, (VALUE)&sarg, &state);
        if (state) {
            rb_io_close(arg.io);
            rb_jump_tag(state);
        }
    }
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}

.binwrite(path, string, offset = 0) ⇒ Integer

Behaves like IO.write, except that the stream is opened in binary mode with ASCII-8BIT encoding.

When called from class IO (but not subclasses of IO), this method has potential security vulnerabilities if called with untrusted input; see Command Injection.

Returns:



12436
12437
12438
12439
12440
# File 'io.c', line 12436

static VALUE
rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
{
    return io_s_write(argc, argv, io, 1);
}

.copy_stream(src, dst, src_length = nil, src_offset = 0) ⇒ Integer

Copies from the given src to the given dst, returning the number of bytes copied.

  • The given src must be one of the following:

    • The path to a readable file, from which source data is to be read.

    • An IO-like object, opened for reading and capable of responding to method :readpartial or method :read.

  • The given dst must be one of the following:

    • The path to a writable file, to which data is to be written.

    • An IO-like object, opened for writing and capable of responding to method :write.

The examples here use file t.txt as source:

File.read('t.txt')
# => "First line\nSecond line\n\nThird line\nFourth line\n"
File.read('t.txt').size # => 47

If only arguments src and dst are given, the entire source stream is copied:

# Paths.
IO.copy_stream('t.txt', 't.tmp')  # => 47

# IOs (recall that a File is also an IO).
src_io = File.open('t.txt', 'r') # => #<File:t.txt>
dst_io = File.open('t.tmp', 'w') # => #<File:t.tmp>
IO.copy_stream(src_io, dst_io)   # => 47
src_io.close
dst_io.close

With argument src_length a non-negative integer, no more than that many bytes are copied:

IO.copy_stream('t.txt', 't.tmp', 10) # => 10
File.read('t.tmp')                   # => "First line"

With argument src_offset also given, the source stream is read beginning at that offset:

IO.copy_stream('t.txt', 't.tmp', 11, 11) # => 11
IO.read('t.tmp')                         # => "Second line"

Returns:



13405
13406
13407
13408
13409
13410
13411
13412
13413
13414
13415
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434
# File 'io.c', line 13405

static VALUE
rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
{
    VALUE src, dst, length, src_offset;
    struct copy_stream_struct st;

    MEMZERO(&st, struct copy_stream_struct, 1);

    rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);

    st.src = src;
    st.dst = dst;

    st.src_fptr = NULL;
    st.dst_fptr = NULL;

    if (NIL_P(length))
        st.copy_length = (rb_off_t)-1;
    else
        st.copy_length = NUM2OFFT(length);

    if (NIL_P(src_offset))
        st.src_offset = (rb_off_t)-1;
    else
        st.src_offset = NUM2OFFT(src_offset);

    rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);

    return OFFT2NUM(st.total);
}

.for_fd(fd, mode = 'r', **opts) ⇒ IO

Synonym for IO.new.

Returns:



9697
9698
9699
9700
9701
9702
9703
# File 'io.c', line 9697

static VALUE
rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
{
    VALUE io = rb_obj_alloc(klass);
    rb_io_initialize(argc, argv, io);
    return io;
}

.foreach(path, sep = $/, **opts) {|line| ... } ⇒ nil .foreach(path, limit, **opts) {|line| ... } ⇒ nil .foreach(path, sep, limit, **opts) {|line| ... } ⇒ nil .foreach(...) ⇒ Object

Calls the block with each successive line read from the stream.

When called from class IO (but not subclasses of IO), this method has potential security vulnerabilities if called with untrusted input; see Command Injection.

The first argument must be a string that is the path to a file.

With only argument path given, parses lines from the file at the given path, as determined by the default line separator, and calls the block with each successive line:

File.foreach('t.txt') {|line| p line }

Output: the same as above.

For both forms, command and path, the remaining arguments are the same.

With argument sep given, parses lines as determined by that line separator (see Line Separator):

File.foreach('t.txt', 'li') {|line| p line }

Output:

"First li"
"ne\nSecond li"
"ne\n\nThird li"
"ne\nFourth li"
"ne\n"

Each paragraph:

File.foreach('t.txt', '') {|paragraph| p paragraph }

Output:

"First line\nSecond line\n\n"
"Third line\nFourth line\n"

With argument limit given, parses lines as determined by the default line separator and the given line-length limit (see Line Separator and Line Limit):

File.foreach('t.txt', 7) {|line| p line }

Output:

"First l"
"ine\n"
"Second "
"line\n"
"\n"
"Third l"
"ine\n"
"Fourth l"
"line\n"

With arguments sep and limit given, combines the two behaviors (see Line Separator and Line Limit).

Optional keyword arguments opts specify:

Returns an Enumerator if no block is given.

Overloads:

  • .foreach(path, sep = $/, **opts) {|line| ... } ⇒ nil

    Yields:

    • (line)

    Returns:

    • (nil)
  • .foreach(path, limit, **opts) {|line| ... } ⇒ nil

    Yields:

    • (line)

    Returns:

    • (nil)
  • .foreach(path, sep, limit, **opts) {|line| ... } ⇒ nil

    Yields:

    • (line)

    Returns:

    • (nil)


12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
# File 'io.c', line 12083

static VALUE
rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
{
    VALUE opt;
    int orig_argc = argc;
    struct foreach_arg arg;
    struct getline_arg garg;

    argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
    RETURN_ENUMERATOR(self, orig_argc, argv);
    extract_getline_args(argc-1, argv+1, &garg);
    open_key_args(self, argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    extract_getline_opts(opt, &garg);
    check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
    return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
}

.new(*args) ⇒ Object

:nodoc:



9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
# File 'io.c', line 9676

static VALUE
rb_io_s_new(int argc, VALUE *argv, VALUE klass)
{
    if (rb_block_given_p()) {
        VALUE cname = rb_obj_as_string(klass);

        rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
                cname, cname);
    }
    return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
}

.open(*args) ⇒ Object

call-seq:

IO.open(fd, mode = 'r', **opts)             -> io
IO.open(fd, mode = 'r', **opts) {|io| ... } -> object

Creates a new IO object, via IO.new with the given arguments.

With no block given, returns the IO object.

With a block given, calls the block with the IO object and returns the block’s value.



8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
# File 'io.c', line 8164

static VALUE
rb_io_s_open(int argc, VALUE *argv, VALUE klass)
{
    VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);

    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, io, io_close, io);
    }

    return io;
}

.pipe(**opts) ⇒ Array .pipe(enc, **opts) ⇒ Array .pipe(ext_enc, int_enc, **opts) ⇒ Array .pipe(**opts) {|read_io, write_io| ... } ⇒ Object .pipe(enc, **opts) {|read_io, write_io| ... } ⇒ Object .pipe(ext_enc, int_enc, **opts) {|read_io, write_io| ... } ⇒ Object

Creates a pair of pipe endpoints, read_io and write_io, connected to each other.

If argument enc_string is given, it must be a string containing one of:

  • The name of the encoding to be used as the external encoding.

  • The colon-separated names of two encodings to be used as the external and internal encodings.

If argument int_enc is given, it must be an Encoding object or encoding name string that specifies the internal encoding to be used; if argument ext_enc is also given, it must be an Encoding object or encoding name string that specifies the external encoding to be used.

The string read from read_io is tagged with the external encoding; if an internal encoding is also specified, the string is converted to, and tagged with, that encoding.

If any encoding is specified, optional hash arguments specify the conversion option.

Optional keyword arguments opts specify:

With no block given, returns the two endpoints in an array:

IO.pipe # => [#<IO:fd 4>, #<IO:fd 5>]

With a block given, calls the block with the two endpoints; closes both endpoints and returns the value of the block:

IO.pipe {|read_io, write_io| p read_io; p write_io }

Output:

#<IO:fd 6>
#<IO:fd 7>

Not available on all platforms.

In the example below, the two processes close the ends of the pipe that they are not using. This is not just a cosmetic nicety. The read end of a pipe will not generate an end of file condition if there are any writers with the pipe still open. In the case of the parent process, the rd.read will never return if it does not first issue a wr.close:

rd, wr = IO.pipe

if fork
  wr.close
  puts "Parent got: <#{rd.read}>"
  rd.close
  Process.wait
else
  rd.close
  puts 'Sending message to parent'
  wr.write "Hi Dad"
  wr.close
end

produces:

Sending message to parent
Parent got: <Hi Dad>

Overloads:

  • .pipe(**opts) ⇒ Array

    Returns:

  • .pipe(enc, **opts) ⇒ Array

    Returns:

  • .pipe(ext_enc, int_enc, **opts) ⇒ Array

    Returns:

  • .pipe(**opts) {|read_io, write_io| ... } ⇒ Object

    Yields:

    • (read_io, write_io)

    Returns:

  • .pipe(enc, **opts) {|read_io, write_io| ... } ⇒ Object

    Yields:

    • (read_io, write_io)

    Returns:

  • .pipe(ext_enc, int_enc, **opts) {|read_io, write_io| ... } ⇒ Object

    Yields:

    • (read_io, write_io)

    Returns:



11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
11927
11928
11929
11930
11931
11932
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951
11952
11953
# File 'io.c', line 11870

static VALUE
rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
{
    int pipes[2], state;
    VALUE r, w, args[3], v1, v2;
    VALUE opt;
    rb_io_t *fptr, *fptr2;
    struct io_encoding_set_args ies_args;
    int fmode = 0;
    VALUE ret;

    argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
    if (rb_pipe(pipes) < 0)
        rb_sys_fail(0);

    args[0] = klass;
    args[1] = INT2NUM(pipes[0]);
    args[2] = INT2FIX(O_RDONLY);
    r = rb_protect(io_new_instance, (VALUE)args, &state);
    if (state) {
        close(pipes[0]);
        close(pipes[1]);
        rb_jump_tag(state);
    }
    GetOpenFile(r, fptr);

    ies_args.fptr = fptr;
    ies_args.v1 = v1;
    ies_args.v2 = v2;
    ies_args.opt = opt;
    rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
    if (state) {
        close(pipes[1]);
        io_close(r);
        rb_jump_tag(state);
    }

    args[1] = INT2NUM(pipes[1]);
    args[2] = INT2FIX(O_WRONLY);
    w = rb_protect(io_new_instance, (VALUE)args, &state);
    if (state) {
        close(pipes[1]);
        if (!NIL_P(r)) rb_io_close(r);
        rb_jump_tag(state);
    }
    GetOpenFile(w, fptr2);
    rb_io_synchronized(fptr2);

    extract_binmode(opt, &fmode);

    if ((fmode & FMODE_BINMODE) && NIL_P(v1)) {
        rb_io_ascii8bit_binmode(r);
        rb_io_ascii8bit_binmode(w);
    }

#if DEFAULT_TEXTMODE
    if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr->mode &= ~FMODE_TEXTMODE;
        setmode(fptr->fd, O_BINARY);
    }
#if RUBY_CRLF_ENVIRONMENT
    if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
        fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
    }
#endif
#endif
    fptr->mode |= fmode;
#if DEFAULT_TEXTMODE
    if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr2->mode &= ~FMODE_TEXTMODE;
        setmode(fptr2->fd, O_BINARY);
    }
#endif
    fptr2->mode |= fmode;

    ret = rb_assoc_new(r, w);
    if (rb_block_given_p()) {
        VALUE rw[2];
        rw[0] = r;
        rw[1] = w;
        return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
    }
    return ret;
}

.popen(env = {}, cmd, mode = 'r', **opts) ⇒ IO .popen(env = ) { ... } ⇒ Object

Executes the given command cmd as a subprocess whose $stdin and $stdout are connected to a new stream io.

This method has potential security vulnerabilities if called with untrusted input; see Command Injection.

If no block is given, returns the new stream, which depending on given mode may be open for reading, writing, or both. The stream should be explicitly closed (eventually) to avoid resource leaks.

If a block is given, the stream is passed to the block (again, open for reading, writing, or both); when the block exits, the stream is closed, and the block’s value is assigned to global variable $? and returned.

Optional argument mode may be any valid IO mode. See Access Modes.

Required argument cmd determines which of the following occurs:

  • The process forks.

  • A specified program runs in a shell.

  • A specified program runs with specified arguments.

  • A specified program runs with specified arguments and a specified argv0.

Each of these is detailed below.

The optional hash argument env specifies name/value pairs that are to be added to the environment variables for the subprocess:

IO.popen({'FOO' => 'bar'}, 'ruby', 'r+') do |pipe|
  pipe.puts 'puts ENV["FOO"]'
  pipe.close_write
  pipe.gets
end => "bar\n"

Optional keyword arguments opts specify:

Forked Process

When argument cmd is the 1-character string '-', causes the process to fork:

IO.popen('-') do |pipe|
  if pipe
    $stderr.puts "In parent, child pid is #{pipe.pid}\n"
  else
    $stderr.puts "In child, pid is #{$$}\n"
  end
end

Output:

In parent, child pid is 26253
In child, pid is 26253

Note that this is not supported on all platforms.

Shell Subprocess

When argument cmd is a single string (but not '-'), the program named cmd is run as a shell command:

IO.popen('uname') do |pipe|
  pipe.readlines
end

Output:

["Linux\n"]

Another example:

IO.popen('/bin/sh', 'r+') do |pipe|
  pipe.puts('ls')
  pipe.close_write
  $stderr.puts pipe.readlines.size
end

Output:

213

Program Subprocess

When argument cmd is an array of strings, the program named cmd[0] is run with all elements of cmd as its arguments:

IO.popen(['du', '..', '.']) do |pipe|
  $stderr.puts pipe.readlines.size
end

Output:

1111

Program Subprocess with argv0

When argument cmd is an array whose first element is a 2-element string array and whose remaining elements (if any) are strings:

  • cmd[0][0] (the first string in the nested array) is the name of a program that is run.

  • cmd[0][1] (the second string in the nested array) is set as the program’s argv[0].

  • cmd[1..-1] (the strings in the outer array) are the program’s arguments.

Example (sets $0 to ‘foo’):

IO.popen([['/bin/sh', 'foo'], '-c', 'echo $0']).read # => "foo\n"

Some Special Examples

# Set IO encoding.
IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
  euc_jp_string = nkf_io.read
}

# Merge standard output and standard error using Kernel#spawn option. See Kernel#spawn.
IO.popen(["ls", "/", :err=>[:child, :out]]) do |io|
  ls_result_with_error = io.read
end

# Use mixture of spawn options and IO options.
IO.popen(["ls", "/"], :err=>[:child, :out]) do |io|
  ls_result_with_error = io.read
end

 f = IO.popen("uname")
 p f.readlines
 f.close
 puts "Parent is #{Process.pid}"
 IO.popen("date") {|f| puts f.gets }
 IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
 p $?
 IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
   f.puts "bar"; f.close_write; puts f.gets
 }

Output (from last section):

["Linux\n"]
Parent is 21346
Thu Jan 15 22:41:19 JST 2009
21346 is here, f is #<IO:fd 3>
21352 is here, f is nil
#<Process::Status: pid 21352 exit 0>
<foo>bar;zot;

Raises exceptions that IO.pipe and Kernel.spawn raise.

Overloads:

  • .popen(env = {}, cmd, mode = 'r', **opts) ⇒ IO

    Returns:

  • .popen(env = ) { ... } ⇒ Object

    Yields:

    Returns:



7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
# File 'io.c', line 7982

static VALUE
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
{
    VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil;

    if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
    if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
    switch (argc) {
      case 2:
        pmode = argv[1];
      case 1:
        pname = argv[0];
        break;
      default:
        {
            int ex = !NIL_P(opt);
            rb_error_arity(argc + ex, 1 + ex, 2 + ex);
        }
    }
    return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
}

.read(path, length = nil, offset = 0, **opts) ⇒ String?

Opens the stream, reads and returns some or all of its content, and closes the stream; returns nil if no bytes were read.

When called from class IO (but not subclasses of IO), this method has potential security vulnerabilities if called with untrusted input; see Command Injection.

The first argument must be a string that is the path to a file.

With only argument path given, reads in text mode and returns the entire content of the file at the given path:

IO.read('t.txt')
# => "First line\nSecond line\n\nThird line\nFourth line\n"

On Windows, text mode can terminate reading and leave bytes in the file unread when encountering certain special bytes. Consider using IO.binread if all bytes in the file should be read.

With argument length, returns length bytes if available:

IO.read('t.txt', 7) # => "First l"
IO.read('t.txt', 700)
# => "First line\r\nSecond line\r\n\r\nFourth line\r\nFifth line\r\n"

With arguments length and offset, returns length bytes if available, beginning at the given offset:

IO.read('t.txt', 10, 2)   # => "rst line\nS"
IO.read('t.txt', 10, 200) # => nil

Optional keyword arguments opts specify:

Returns:



12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
# File 'io.c', line 12240

static VALUE
rb_io_s_read(int argc, VALUE *argv, VALUE io)
{
    VALUE opt, offset;
    long off;
    struct foreach_arg arg;

    argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
    if (!NIL_P(offset) && (off = NUM2LONG(offset)) < 0) {
        rb_raise(rb_eArgError, "negative offset %ld given", off);
    }
    open_key_args(io, argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    if (!NIL_P(offset)) {
        struct seek_arg sarg;
        int state = 0;
        sarg.io = arg.io;
        sarg.offset = offset;
        sarg.mode = SEEK_SET;
        rb_protect(seek_before_access, (VALUE)&sarg, &state);
        if (state) {
            rb_io_close(arg.io);
            rb_jump_tag(state);
        }
        if (arg.argc == 2) arg.argc = 1;
    }
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}

.readlines(path, sep = $/, **opts) ⇒ Array .readlines(path, limit, **opts) ⇒ Array .readlines(path, sep, limit, **opts) ⇒ Array

Returns an array of all lines read from the stream.

When called from class IO (but not subclasses of IO), this method has potential security vulnerabilities if called with untrusted input; see Command Injection.

The first argument must be a string that is the path to a file.

With only argument path given, parses lines from the file at the given path, as determined by the default line separator, and returns those lines in an array:

IO.readlines('t.txt')
# => ["First line\n", "Second line\n", "\n", "Third line\n", "Fourth line\n"]

With argument sep given, parses lines as determined by that line separator (see Line Separator):

# Ordinary separator.
IO.readlines('t.txt', 'li')
# =>["First li", "ne\nSecond li", "ne\n\nThird li", "ne\nFourth li", "ne\n"]
# Get-paragraphs separator.
IO.readlines('t.txt', '')
# => ["First line\nSecond line\n\n", "Third line\nFourth line\n"]
# Get-all separator.
IO.readlines('t.txt', nil)
# => ["First line\nSecond line\n\nThird line\nFourth line\n"]

With argument limit given, parses lines as determined by the default line separator and the given line-length limit (see Line Separator and Line Limit:

IO.readlines('t.txt', 7)
# => ["First l", "ine\n", "Second ", "line\n", "\n", "Third l", "ine\n", "Fourth ", "line\n"]

With arguments sep and limit given, combines the two behaviors (see Line Separator and Line Limit).

Optional keyword arguments opts specify:

Overloads:

  • .readlines(path, sep = $/, **opts) ⇒ Array

    Returns:

  • .readlines(path, limit, **opts) ⇒ Array

    Returns:

  • .readlines(path, sep, limit, **opts) ⇒ Array

    Returns:



12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
# File 'io.c', line 12161

static VALUE
rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
{
    VALUE opt;
    struct foreach_arg arg;
    struct getline_arg garg;

    argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
    extract_getline_args(argc-1, argv+1, &garg);
    open_key_args(io, argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    extract_getline_opts(opt, &garg);
    check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
    return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
}

.select(read_ios, write_ios = [], error_ios = [], timeout = nil) ⇒ Array?

Invokes system call select(2), which monitors multiple file descriptors, waiting until one or more of the file descriptors becomes ready for some class of I/O operation.

Not implemented on all platforms.

Each of the arguments read_ios, write_ios, and error_ios is an array of IO objects.

Argument timeout is a numeric value (such as integer or float) timeout interval in seconds.

The method monitors the IO objects given in all three arrays, waiting for some to be ready; returns a 3-element array whose elements are:

  • An array of the objects in read_ios that are ready for reading.

  • An array of the objects in write_ios that are ready for writing.

  • An array of the objects in error_ios have pending exceptions.

If no object becomes ready within the given timeout, nil is returned.

IO.select peeks the buffer of IO objects for testing readability. If the IO buffer is not empty, IO.select immediately notifies readability. This “peek” only happens for IO objects. It does not happen for IO-like objects such as OpenSSL::SSL::SSLSocket.

The best way to use IO.select is invoking it after non-blocking methods such as #read_nonblock, #write_nonblock, etc. The methods raise an exception which is extended by IO::WaitReadable or IO::WaitWritable. The modules notify how the caller should wait with IO.select. If IO::WaitReadable is raised, the caller should wait for reading. If IO::WaitWritable is raised, the caller should wait for writing.

So, blocking read (#readpartial) can be emulated using #read_nonblock and IO.select as follows:

begin
  result = io_like.read_nonblock(maxlen)
rescue IO::WaitReadable
  IO.select([io_like])
  retry
rescue IO::WaitWritable
  IO.select(nil, [io_like])
  retry
end

Especially, the combination of non-blocking methods and IO.select is preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It has #to_io method to return underlying IO object. IO.select calls #to_io to obtain the file descriptor to wait.

This means that readability notified by IO.select doesn’t mean readability from OpenSSL::SSL::SSLSocket object.

The most likely situation is that OpenSSL::SSL::SSLSocket buffers some data. IO.select doesn’t see the buffer. So IO.select can block when OpenSSL::SSL::SSLSocket#readpartial doesn’t block.

However, several more complicated situations exist.

SSL is a protocol which is sequence of records. The record consists of multiple bytes. So, the remote side of SSL sends a partial record, IO.select notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a byte and OpenSSL::SSL::SSLSocket#readpartial will block.

Also, the remote side can request SSL renegotiation which forces the local SSL engine to write some data. This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write system call and it can block. In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises IO::WaitWritable instead of blocking. So, the caller should wait for ready for writability as above example.

The combination of non-blocking methods and IO.select is also useful for streams such as tty, pipe socket socket when multiple processes read from a stream.

Finally, Linux kernel developers don’t guarantee that readability of select(2) means readability of following read(2) even for a single process; see select(2)

Invoking IO.select before IO#readpartial works well as usual. However it is not the best way to use IO.select.

The writability notified by select(2) doesn’t show how many bytes are writable. IO#write method blocks until given whole string is written. So, IO#write(two or more bytes) can block after writability is notified by IO.select. IO#write_nonblock is required to avoid the blocking.

Blocking write (#write) can be emulated using #write_nonblock and IO.select as follows: IO::WaitReadable should also be rescued for SSL renegotiation in OpenSSL::SSL::SSLSocket.

while 0 < string.bytesize
  begin
    written = io_like.write_nonblock(string)
  rescue IO::WaitReadable
    IO.select([io_like])
    retry
  rescue IO::WaitWritable
    IO.select(nil, [io_like])
    retry
  end
  string = string.byteslice(written..-1)
end

Example:

rp, wp = IO.pipe
mesg = "ping "
100.times {
  # IO.select follows IO#read.  Not the best way to use IO.select.
  rs, ws, = IO.select([rp], [wp])
  if r = rs[0]
    ret = r.read(5)
    print ret
    case ret
    when /ping/
      mesg = "pong\n"
    when /pong/
      mesg = "ping "
    end
  end
  if w = ws[0]
    w.write(mesg)
  end
}

Output:

ping pong
ping pong
ping pong
(snipped)
ping

Returns:



11116
11117
11118
11119
11120
11121
11122
11123
11124
11125
11126
11127
11128
11129
11130
11131
11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143
11144
# File 'io.c', line 11116

static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
    VALUE scheduler = rb_fiber_scheduler_current();
    if (scheduler != Qnil) {
        // It's optionally supported.
        VALUE result = rb_fiber_scheduler_io_selectv(scheduler, argc, argv);
        if (!UNDEF_P(result)) return result;
    }

    VALUE timeout;
    struct select_args args;
    struct timeval timerec;
    int i;

    rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
    if (NIL_P(timeout)) {
        args.timeout = 0;
    }
    else {
        timerec = rb_time_interval(timeout);
        args.timeout = &timerec;
    }

    for (i = 0; i < numberof(args.fdsets); ++i)
        rb_fd_init(&args.fdsets[i]);

    return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
}

.sysopen(path, mode = 'r', perm = 0666) ⇒ Integer

Opens the file at the given path with the given mode and permissions; returns the integer file descriptor.

If the file is to be readable, it must exist; if the file is to be writable and does not exist, it is created with the given permissions:

File.write('t.tmp', '')  # => 0
IO.sysopen('t.tmp')      # => 8
IO.sysopen('t.tmp', 'w') # => 9

Returns:



8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
# File 'io.c', line 8194

static VALUE
rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
{
    VALUE fname, vmode, vperm;
    VALUE intmode;
    int oflags, fd;
    mode_t perm;

    rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
    FilePathValue(fname);

    if (NIL_P(vmode))
        oflags = O_RDONLY;
    else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
        oflags = NUM2INT(intmode);
    else {
        StringValue(vmode);
        oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
    }
    if (NIL_P(vperm)) perm = 0666;
    else              perm = NUM2MODET(vperm);

    RB_GC_GUARD(fname) = rb_str_new4(fname);
    fd = rb_sysopen(fname, oflags, perm);
    return INT2NUM(fd);
}

.try_convert(object) ⇒ nil

Attempts to convert object into an IO object via method to_io; returns the new IO object if successful, or nil otherwise:

IO.try_convert(STDOUT)   # => #<IO:<STDOUT>>
IO.try_convert(ARGF)     # => #<IO:<STDIN>>
IO.try_convert('STDOUT') # => nil

Returns:

  • (nil)


912
913
914
915
916
# File 'io.c', line 912

static VALUE
rb_io_s_try_convert(VALUE dummy, VALUE io)
{
    return rb_io_check_io(io);
}

.write(path, data, offset = 0, **opts) ⇒ Integer

Opens the stream, writes the given data to it, and closes the stream; returns the number of bytes written.

When called from class IO (but not subclasses of IO), this method has potential security vulnerabilities if called with untrusted input; see Command Injection.

The first argument must be a string that is the path to a file.

With only argument path given, writes the given data to the file at that path:

IO.write('t.tmp', 'abc')    # => 3
File.read('t.tmp')          # => "abc"

If offset is zero (the default), the file is overwritten:

IO.write('t.tmp', 'A')      # => 1
File.read('t.tmp')          # => "A"

If offset in within the file content, the file is partly overwritten:

IO.write('t.tmp', 'abcdef') # => 3
File.read('t.tmp')          # => "abcdef"
# Offset within content.
IO.write('t.tmp', '012', 2) # => 3
File.read('t.tmp')          # => "ab012f"

If offset is outside the file content, the file is padded with null characters "\u0000":

IO.write('t.tmp', 'xyz', 10) # => 3
File.read('t.tmp')           # => "ab012f\u0000\u0000\u0000\u0000xyz"

Optional keyword arguments opts specify:

Returns:



12417
12418
12419
12420
12421
# File 'io.c', line 12417

static VALUE
rb_io_s_write(int argc, VALUE *argv, VALUE io)
{
    return io_s_write(argc, argv, io, 0);
}

Instance Method Details

#<<(object) ⇒ self

Writes the given object to self, which must be opened for writing (see Access Modes); returns self; if object is not a string, it is converted via method to_s:

$stdout << 'Hello' << ', ' << 'World!' << "\n"
$stdout << 'foo' << :bar << 2 << "\n"

Output:

Hello, World!
foobar2

Returns:

  • (self)


2349
2350
2351
2352
2353
2354
# File 'io.c', line 2349

VALUE
rb_io_addstr(VALUE io, VALUE str)
{
    rb_io_write(io, str);
    return io;
}

#advise(advice, offset = 0, len = 0) ⇒ nil

Invokes Posix system call posix_fadvise(2), which announces an intention to access data from the current file in a particular manner.

The arguments and results are platform-dependent.

The relevant data is specified by:

  • offset: The offset of the first byte of data.

  • len: The number of bytes to be accessed; if len is zero, or is larger than the number of bytes remaining, all remaining bytes will be accessed.

Argument advice is one of the following symbols:

  • :normal: The application has no advice to give about its access pattern for the specified data. If no advice is given for an open file, this is the default assumption.

  • :sequential: The application expects to access the specified data sequentially (with lower offsets read before higher ones).

  • :random: The specified data will be accessed in random order.

  • :noreuse: The specified data will be accessed only once.

  • :willneed: The specified data will be accessed in the near future.

  • :dontneed: The specified data will not be accessed in the near future.

Not implemented on all platforms.

Returns:

  • (nil)


10942
10943
10944
10945
10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
# File 'io.c', line 10942

static VALUE
rb_io_advise(int argc, VALUE *argv, VALUE io)
{
    VALUE advice, offset, len;
    rb_off_t off, l;
    rb_io_t *fptr;

    rb_scan_args(argc, argv, "12", &advice, &offset, &len);
    advice_arg_check(advice);

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
    l   = NIL_P(len)    ? 0 : NUM2OFFT(len);

#ifdef HAVE_POSIX_FADVISE
    return do_io_advise(fptr, advice, off, l);
#else
    ((void)off, (void)l);	/* Ignore all hint */
    return Qnil;
#endif
}

#autoclose=(bool) ⇒ Boolean

Sets auto-close flag.

f = File.open(File::NULL)
IO.for_fd(f.fileno).close
f.gets # raises Errno::EBADF

f = File.open(File::NULL)
g = IO.for_fd(f.fileno)
g.autoclose = false
g.close
f.gets # won't cause Errno::EBADF

Returns:

  • (Boolean)


9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
# File 'io.c', line 9738

static VALUE
rb_io_set_autoclose(VALUE io, VALUE autoclose)
{
    rb_io_t *fptr;
    GetOpenFile(io, fptr);
    if (!RTEST(autoclose))
        fptr->mode |= FMODE_EXTERNAL;
    else
        fptr->mode &= ~FMODE_EXTERNAL;
    return autoclose;
}

#autoclose?Boolean

Returns true if the underlying file descriptor of ios will be closed at its finalization or at calling #close, otherwise false.

Returns:

  • (Boolean)


9713
9714
9715
9716
9717
9718
9719
# File 'io.c', line 9713

static VALUE
rb_io_autoclose_p(VALUE io)
{
    rb_io_t *fptr = RFILE(io)->fptr;
    rb_io_check_closed(fptr);
    return RBOOL(!(fptr->mode & FMODE_EXTERNAL));
}

#binmodeself

Sets the stream’s data mode as binary (see Data Mode).

A stream’s data mode may not be changed from binary to text.

Returns:

  • (self)


6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
# File 'io.c', line 6405

static VALUE
rb_io_binmode_m(VALUE io)
{
    VALUE write_io;

    rb_io_ascii8bit_binmode(io);

    write_io = GetWriteIO(io);
    if (write_io != io)
        rb_io_ascii8bit_binmode(write_io);
    return io;
}

#binmode?Boolean

Returns true if the stream is on binary mode, false otherwise. See Data Mode.

Returns:

  • (Boolean)


6426
6427
6428
6429
6430
6431
6432
# File 'io.c', line 6426

static VALUE
rb_io_binmode_p(VALUE io)
{
    rb_io_t *fptr;
    GetOpenFile(io, fptr);
    return RBOOL(fptr->mode & FMODE_BINMODE);
}

#closenil

Closes the stream for both reading and writing if open for either or both; returns nil. See Open and Closed Streams.

If the stream is open for writing, flushes any buffered writes to the operating system before closing.

If the stream was opened by IO.popen, sets global variable $? (child exit status).

It is not an error to close an IO object that has already been closed. It just returns nil.

Example:

IO.popen('ruby', 'r+') do |pipe|
  puts pipe.closed?
  pipe.close
  puts $?
  puts pipe.closed?
end

Output:

false
pid 13760 exit 0
true

Related: IO#close_read, IO#close_write, IO#closed?.

Returns:

  • (nil)


5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
# File 'io.c', line 5800

static VALUE
rb_io_close_m(VALUE io)
{
    rb_io_t *fptr = rb_io_get_fptr(io);
    if (fptr->fd < 0) {
        return Qnil;
    }
    rb_io_close(io);
    return Qnil;
}

#close_on_exec=(bool) ⇒ Boolean

Sets a close-on-exec flag.

f = File.open(File::NULL)
f.close_on_exec = true
system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
f.closed?                #=> false

Ruby sets close-on-exec flags of all file descriptors by default since Ruby 2.0.0. So you don’t need to set by yourself. Also, unsetting a close-on-exec flag can cause file descriptor leak if another thread use fork() and exec() (via system() method for example). If you really needs file descriptor inheritance to child process, use spawn()‘s argument such as fd=>fd.

Returns:

  • (Boolean)


5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
# File 'io.c', line 5365

static VALUE
rb_io_set_close_on_exec(VALUE io, VALUE arg)
{
    int flag = RTEST(arg) ? FD_CLOEXEC : 0;
    rb_io_t *fptr;
    VALUE write_io;
    int fd, ret;

    write_io = GetWriteIO(io);
    if (io != write_io) {
        GetOpenFile(write_io, fptr);
        if (fptr && 0 <= (fd = fptr->fd)) {
            if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
            if ((ret & FD_CLOEXEC) != flag) {
                ret = (ret & ~FD_CLOEXEC) | flag;
                ret = fcntl(fd, F_SETFD, ret);
                if (ret != 0) rb_sys_fail_path(fptr->pathv);
            }
        }

    }

    GetOpenFile(io, fptr);
    if (fptr && 0 <= (fd = fptr->fd)) {
        if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
        if ((ret & FD_CLOEXEC) != flag) {
            ret = (ret & ~FD_CLOEXEC) | flag;
            ret = fcntl(fd, F_SETFD, ret);
            if (ret != 0) rb_sys_fail_path(fptr->pathv);
        }
    }
    return Qnil;
}

#close_on_exec?Boolean

Returns true if the stream will be closed on exec, false otherwise:

f = File.open('t.txt')
f.close_on_exec? # => true
f.close_on_exec = false
f.close_on_exec? # => false
f.close

Returns:

  • (Boolean)


5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
# File 'io.c', line 5317

static VALUE
rb_io_close_on_exec_p(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;
    int fd, ret;

    write_io = GetWriteIO(io);
    if (io != write_io) {
        GetOpenFile(write_io, fptr);
        if (fptr && 0 <= (fd = fptr->fd)) {
            if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
            if (!(ret & FD_CLOEXEC)) return Qfalse;
        }
    }

    GetOpenFile(io, fptr);
    if (fptr && 0 <= (fd = fptr->fd)) {
        if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
        if (!(ret & FD_CLOEXEC)) return Qfalse;
    }
    return Qtrue;
}

#close_readnil

Closes the stream for reading if open for reading; returns nil. See Open and Closed Streams.

If the stream was opened by IO.popen and is also closed for writing, sets global variable $? (child exit status).

Example:

IO.popen('ruby', 'r+') do |pipe|
  puts pipe.closed?
  pipe.close_write
  puts pipe.closed?
  pipe.close_read
  puts $?
  puts pipe.closed?
end

Output:

false
false
pid 14748 exit 0
true

Related: IO#close, IO#close_write, IO#closed?.

Returns:

  • (nil)


5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
# File 'io.c', line 5916

static VALUE
rb_io_close_read(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;

    fptr = rb_io_get_fptr(rb_io_taint_check(io));
    if (fptr->fd < 0) return Qnil;
    if (is_socket(fptr->fd, fptr->pathv)) {
#ifndef SHUT_RD
# define SHUT_RD 0
#endif
        if (shutdown(fptr->fd, SHUT_RD) < 0)
            rb_sys_fail_path(fptr->pathv);
        fptr->mode &= ~FMODE_READABLE;
        if (!(fptr->mode & FMODE_WRITABLE))
            return rb_io_close(io);
        return Qnil;
    }

    write_io = GetWriteIO(io);
    if (io != write_io) {
        rb_io_t *wfptr;
        wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
        wfptr->pid = fptr->pid;
        fptr->pid = 0;
        RFILE(io)->fptr = wfptr;
        /* bind to write_io temporarily to get rid of memory/fd leak */
        fptr->tied_io_for_writing = 0;
        RFILE(write_io)->fptr = fptr;
        rb_io_fptr_cleanup(fptr, FALSE);
        /* should not finalize fptr because another thread may be reading it */
        return Qnil;
    }

    if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
        rb_raise(rb_eIOError, "closing non-duplex IO for reading");
    }
    return rb_io_close(io);
}

#close_writenil

Closes the stream for writing if open for writing; returns nil. See Open and Closed Streams.

Flushes any buffered writes to the operating system before closing.

If the stream was opened by IO.popen and is also closed for reading, sets global variable $? (child exit status).

IO.popen('ruby', 'r+') do |pipe|
  puts pipe.closed?
  pipe.close_read
  puts pipe.closed?
  pipe.close_write
  puts $?
  puts pipe.closed?
end

Output:

false
false
pid 15044 exit 0
true

Related: IO#close, IO#close_read, IO#closed?.

Returns:

  • (nil)


5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
# File 'io.c', line 5989

static VALUE
rb_io_close_write(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;

    write_io = GetWriteIO(io);
    fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
    if (fptr->fd < 0) return Qnil;
    if (is_socket(fptr->fd, fptr->pathv)) {
#ifndef SHUT_WR
# define SHUT_WR 1
#endif
        if (shutdown(fptr->fd, SHUT_WR) < 0)
            rb_sys_fail_path(fptr->pathv);
        fptr->mode &= ~FMODE_WRITABLE;
        if (!(fptr->mode & FMODE_READABLE))
            return rb_io_close(write_io);
        return Qnil;
    }

    if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
        rb_raise(rb_eIOError, "closing non-duplex IO for writing");
    }

    if (io != write_io) {
        fptr = rb_io_get_fptr(rb_io_taint_check(io));
        fptr->tied_io_for_writing = 0;
    }
    rb_io_close(write_io);
    return Qnil;
}

#closed?Boolean

Returns true if the stream is closed for both reading and writing, false otherwise. See Open and Closed Streams.

IO.popen('ruby', 'r+') do |pipe|
  puts pipe.closed?
  pipe.close_read
  puts pipe.closed?
  pipe.close_write
  puts pipe.closed?
end

Output:

false
false
true

Related: IO#close_read, IO#close_write, IO#close.

Returns:

  • (Boolean)


5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
# File 'io.c', line 5865

VALUE
rb_io_closed_p(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;
    rb_io_t *write_fptr;

    write_io = GetWriteIO(io);
    if (io != write_io) {
        write_fptr = RFILE(write_io)->fptr;
        if (write_fptr && 0 <= write_fptr->fd) {
            return Qfalse;
        }
    }

    fptr = rb_io_get_fptr(io);
    return RBOOL(0 > fptr->fd);
}

#each_line(sep = $/, chomp: false) {|line| ... } ⇒ self #each_line(limit, chomp: false) {|line| ... } ⇒ self #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self #each_lineObject

Calls the block with each remaining line read from the stream; returns self. Does nothing if already at end-of-stream; See Line IO.

With no arguments given, reads lines as determined by line separator $/:

f = File.new('t.txt')
f.each_line {|line| p line }
f.each_line {|line| fail 'Cannot happen' }
f.close

Output:

"First line\n"
"Second line\n"
"\n"
"Fourth line\n"
"Fifth line\n"

With only string argument sep given, reads lines as determined by line separator sep; see Line Separator:

f = File.new('t.txt')
f.each_line('li') {|line| p line }
f.close

Output:

"First li"
"ne\nSecond li"
"ne\n\nFourth li"
"ne\nFifth li"
"ne\n"

The two special values for sep are honored:

f = File.new('t.txt')
# Get all into one string.
f.each_line(nil) {|line| p line }
f.close

Output:

"First line\nSecond line\n\nFourth line\nFifth line\n"

f.rewind
# Get paragraphs (up to two line separators).
f.each_line('') {|line| p line }

Output:

"First line\nSecond line\n\n"
"Fourth line\nFifth line\n"

With only integer argument limit given, limits the number of bytes in each line; see Line Limit:

f = File.new('t.txt')
f.each_line(8) {|line| p line }
f.close

Output:

"First li"
"ne\n"
"Second l"
"ine\n"
"\n"
"Fourth l"
"ine\n"
"Fifth li"
"ne\n"

With arguments sep and limit given, combines the two behaviors (see Line Separator and Line Limit).

Optional keyword argument chomp specifies whether line separators are to be omitted:

f = File.new('t.txt')
f.each_line(chomp: true) {|line| p line }
f.close

Output:

"First line"
"Second line"
""
"Fourth line"
"Fifth line"

Returns an Enumerator if no block is given.

Overloads:

  • #each_line(sep = $/, chomp: false) {|line| ... } ⇒ self

    Yields:

    • (line)

    Returns:

    • (self)
  • #each_line(limit, chomp: false) {|line| ... } ⇒ self

    Yields:

    • (line)

    Returns:

    • (self)
  • #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self

    Yields:

    • (line)

    Returns:

    • (self)


4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
# File 'io.c', line 4670

static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
    VALUE str;
    struct getline_arg args;

    RETURN_ENUMERATOR(io, argc, argv);
    prepare_getline_args(argc, argv, &args, io);
    if (args.limit == 0)
        rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
    while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
        rb_yield(str);
    }
    return io;
}

#each_byte {|byte| ... } ⇒ self #each_byteObject

Calls the given block with each byte (0..255) in the stream; returns self. See Byte IO.

f = File.new('t.rus')
a = []
f.each_byte {|b| a << b }
a # => [209, 130, 208, 181, 209, 129, 209, 130]
f.close

Returns an Enumerator if no block is given.

Related: IO#each_char, IO#each_codepoint.

Overloads:

  • #each_byte {|byte| ... } ⇒ self

    Yields:

    • (byte)

    Returns:

    • (self)


4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
# File 'io.c', line 4706

static VALUE
rb_io_each_byte(VALUE io)
{
    rb_io_t *fptr;

    RETURN_ENUMERATOR(io, 0, 0);
    GetOpenFile(io, fptr);

    do {
        while (fptr->rbuf.len > 0) {
            char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
            fptr->rbuf.len--;
            rb_yield(INT2FIX(*p & 0xff));
            rb_io_check_byte_readable(fptr);
            errno = 0;
        }
        READ_CHECK(fptr);
    } while (io_fillbuf(fptr) >= 0);
    return io;
}

#each_char {|c| ... } ⇒ self #each_charObject

Calls the given block with each character in the stream; returns self. See Character IO.

f = File.new('t.rus')
a = []
f.each_char {|c| a << c.ord }
a # => [1090, 1077, 1089, 1090]
f.close

Returns an Enumerator if no block is given.

Related: IO#each_byte, IO#each_codepoint.

Overloads:

  • #each_char {|c| ... } ⇒ self

    Yields:

    • (c)

    Returns:

    • (self)


4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
# File 'io.c', line 4854

static VALUE
rb_io_each_char(VALUE io)
{
    rb_io_t *fptr;
    rb_encoding *enc;
    VALUE c;

    RETURN_ENUMERATOR(io, 0, 0);
    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    enc = io_input_encoding(fptr);
    READ_CHECK(fptr);
    while (!NIL_P(c = io_getc(fptr, enc))) {
        rb_yield(c);
    }
    return io;
}

#each_codepoint {|c| ... } ⇒ self #each_codepointObject

Calls the given block with each codepoint in the stream; returns self:

f = File.new('t.rus')
a = []
f.each_codepoint {|c| a << c }
a # => [1090, 1077, 1089, 1090]
f.close

Returns an Enumerator if no block is given.

Related: IO#each_byte, IO#each_char.

Overloads:

  • #each_codepoint {|c| ... } ⇒ self

    Yields:

    • (c)

    Returns:

    • (self)


4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
# File 'io.c', line 4892

static VALUE
rb_io_each_codepoint(VALUE io)
{
    rb_io_t *fptr;
    rb_encoding *enc;
    unsigned int c;
    int r, n;

    RETURN_ENUMERATOR(io, 0, 0);
    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    READ_CHECK(fptr);
    if (NEED_READCONV(fptr)) {
        SET_BINARY_MODE(fptr);
        r = 1;		/* no invalid char yet */
        for (;;) {
            make_readconv(fptr, 0);
            for (;;) {
                if (fptr->cbuf.len) {
                    if (fptr->encs.enc)
                        r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
                                                  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
                                                  fptr->encs.enc);
                    else
                        r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
                    if (!MBCLEN_NEEDMORE_P(r))
                        break;
                    if (fptr->cbuf.len == fptr->cbuf.capa) {
                        rb_raise(rb_eIOError, "too long character");
                    }
                }
                if (more_char(fptr) == MORE_CHAR_FINISHED) {
                    clear_readconv(fptr);
                    if (!MBCLEN_CHARFOUND_P(r)) {
                        enc = fptr->encs.enc;
                        goto invalid;
                    }
                    return io;
                }
            }
            if (MBCLEN_INVALID_P(r)) {
                enc = fptr->encs.enc;
                goto invalid;
            }
            n = MBCLEN_CHARFOUND_LEN(r);
            if (fptr->encs.enc) {
                c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
                                     fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
                                     fptr->encs.enc);
            }
            else {
                c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
            }
            fptr->cbuf.off += n;
            fptr->cbuf.len -= n;
            rb_yield(UINT2NUM(c));
            rb_io_check_byte_readable(fptr);
        }
    }
    NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
    enc = io_input_encoding(fptr);
    while (io_fillbuf(fptr) >= 0) {
        r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
                                  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
        if (MBCLEN_CHARFOUND_P(r) &&
            (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
            c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
                                 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
            fptr->rbuf.off += n;
            fptr->rbuf.len -= n;
            rb_yield(UINT2NUM(c));
        }
        else if (MBCLEN_INVALID_P(r)) {
            goto invalid;
        }
        else if (MBCLEN_NEEDMORE_P(r)) {
            char cbuf[8], *p = cbuf;
            int more = MBCLEN_NEEDMORE_LEN(r);
            if (more > numberof(cbuf)) goto invalid;
            more += n = fptr->rbuf.len;
            if (more > numberof(cbuf)) goto invalid;
            while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
                   (p += n, (more -= n) > 0)) {
                if (io_fillbuf(fptr) < 0) goto invalid;
                if ((n = fptr->rbuf.len) > more) n = more;
            }
            r = rb_enc_precise_mbclen(cbuf, p, enc);
            if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
            c = rb_enc_codepoint(cbuf, p, enc);
            rb_yield(UINT2NUM(c));
        }
        else {
            continue;
        }
        rb_io_check_byte_readable(fptr);
    }
    return io;

  invalid:
    rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
    UNREACHABLE_RETURN(Qundef);
}

#each_line(sep = $/, chomp: false) {|line| ... } ⇒ self #each_line(limit, chomp: false) {|line| ... } ⇒ self #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self #each_lineObject

Calls the block with each remaining line read from the stream; returns self. Does nothing if already at end-of-stream; See Line IO.

With no arguments given, reads lines as determined by line separator $/:

f = File.new('t.txt')
f.each_line {|line| p line }
f.each_line {|line| fail 'Cannot happen' }
f.close

Output:

"First line\n"
"Second line\n"
"\n"
"Fourth line\n"
"Fifth line\n"

With only string argument sep given, reads lines as determined by line separator sep; see Line Separator:

f = File.new('t.txt')
f.each_line('li') {|line| p line }
f.close

Output:

"First li"
"ne\nSecond li"
"ne\n\nFourth li"
"ne\nFifth li"
"ne\n"

The two special values for sep are honored:

f = File.new('t.txt')
# Get all into one string.
f.each_line(nil) {|line| p line }
f.close

Output:

"First line\nSecond line\n\nFourth line\nFifth line\n"

f.rewind
# Get paragraphs (up to two line separators).
f.each_line('') {|line| p line }

Output:

"First line\nSecond line\n\n"
"Fourth line\nFifth line\n"

With only integer argument limit given, limits the number of bytes in each line; see Line Limit:

f = File.new('t.txt')
f.each_line(8) {|line| p line }
f.close

Output:

"First li"
"ne\n"
"Second l"
"ine\n"
"\n"
"Fourth l"
"ine\n"
"Fifth li"
"ne\n"

With arguments sep and limit given, combines the two behaviors (see Line Separator and Line Limit).

Optional keyword argument chomp specifies whether line separators are to be omitted:

f = File.new('t.txt')
f.each_line(chomp: true) {|line| p line }
f.close

Output:

"First line"
"Second line"
""
"Fourth line"
"Fifth line"

Returns an Enumerator if no block is given.

Overloads:

  • #each_line(sep = $/, chomp: false) {|line| ... } ⇒ self

    Yields:

    • (line)

    Returns:

    • (self)
  • #each_line(limit, chomp: false) {|line| ... } ⇒ self

    Yields:

    • (line)

    Returns:

    • (self)
  • #each_line(sep, limit, chomp: false) {|line| ... } ⇒ self

    Yields:

    • (line)

    Returns:

    • (self)


4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
# File 'io.c', line 4670

static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
    VALUE str;
    struct getline_arg args;

    RETURN_ENUMERATOR(io, argc, argv);
    prepare_getline_args(argc, argv, &args, io);
    if (args.limit == 0)
        rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
    while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
        rb_yield(str);
    }
    return io;
}

#eofBoolean

Returns true if the stream is positioned at its end, false otherwise; see Position:

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

Raises an exception unless the stream is opened for reading; see Mode.

If self is a stream such as pipe or socket, this method blocks until the other end sends some data or closes it:

r, w = IO.pipe
Thread.new { sleep 1; w.close }
r.eof? # => true # After 1-second wait.

r, w = IO.pipe
Thread.new { sleep 1; w.puts "a" }
r.eof?  # => false # After 1-second wait.

r, w = IO.pipe
r.eof?  # blocks forever

Note that this method reads data to the input byte buffer. So IO#sysread may not behave as you intend with IO#eof?, unless you call IO#rewind first (which is not available for some streams).

Returns:

  • (Boolean)


2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
# File 'io.c', line 2694

VALUE
rb_io_eof(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    if (READ_CHAR_PENDING(fptr)) return Qfalse;
    if (READ_DATA_PENDING(fptr)) return Qfalse;
    READ_CHECK(fptr);
#if RUBY_CRLF_ENVIRONMENT
    if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
        return RBOOL(eof(fptr->fd));
    }
#endif
    return RBOOL(io_fillbuf(fptr) < 0);
}

#eofBoolean

Returns true if the stream is positioned at its end, false otherwise; see Position:

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

Raises an exception unless the stream is opened for reading; see Mode.

If self is a stream such as pipe or socket, this method blocks until the other end sends some data or closes it:

r, w = IO.pipe
Thread.new { sleep 1; w.close }
r.eof? # => true # After 1-second wait.

r, w = IO.pipe
Thread.new { sleep 1; w.puts "a" }
r.eof?  # => false # After 1-second wait.

r, w = IO.pipe
r.eof?  # blocks forever

Note that this method reads data to the input byte buffer. So IO#sysread may not behave as you intend with IO#eof?, unless you call IO#rewind first (which is not available for some streams).

Returns:

  • (Boolean)


2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
# File 'io.c', line 2694

VALUE
rb_io_eof(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    if (READ_CHAR_PENDING(fptr)) return Qfalse;
    if (READ_DATA_PENDING(fptr)) return Qfalse;
    READ_CHECK(fptr);
#if RUBY_CRLF_ENVIRONMENT
    if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
        return RBOOL(eof(fptr->fd));
    }
#endif
    return RBOOL(io_fillbuf(fptr) < 0);
}

#external_encodingEncoding?

Returns the Encoding object that represents the encoding of the stream, or nil if the stream is in write mode and no encoding is specified.

See Encodings.

Returns:



13447
13448
13449
13450
13451
13452
13453
13454
13455
13456
13457
13458
13459
13460
13461
# File 'io.c', line 13447

static VALUE
rb_io_external_encoding(VALUE io)
{
    rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;

    if (fptr->encs.enc2) {
        return rb_enc_from_encoding(fptr->encs.enc2);
    }
    if (fptr->mode & FMODE_WRITABLE) {
        if (fptr->encs.enc)
            return rb_enc_from_encoding(fptr->encs.enc);
        return Qnil;
    }
    return rb_enc_from_encoding(io_read_encoding(fptr));
}

#fcntl(integer_cmd, argument) ⇒ Integer

Invokes Posix system call fcntl(2), which provides a mechanism for issuing low-level commands to control or query a file-oriented I/O stream. Arguments and results are platform dependent.

If argument is a number, its value is passed directly; if it is a string, it is interpreted as a binary sequence of bytes. (Array#pack might be a useful way to build this string.)

Not implemented on all platforms.

Returns:



11551
11552
11553
11554
11555
11556
11557
11558
# File 'io.c', line 11551

static VALUE
rb_io_fcntl(int argc, VALUE *argv, VALUE io)
{
    VALUE req, arg;

    rb_scan_args(argc, argv, "11", &req, &arg);
    return rb_fcntl(io, req, arg);
}

#fdatasync0

Immediately writes to disk all data buffered in the stream, via the operating system’s: fdatasync(2), if supported, otherwise via fsync(2), if supported; otherwise raises an exception.

Returns:

  • (0)


2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
# File 'io.c', line 2851

static VALUE
rb_io_fdatasync(VALUE io)
{
    rb_io_t *fptr;

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    if (io_fflush(fptr) < 0)
        rb_sys_fail_on_write(fptr);

    if ((int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
        return INT2FIX(0);

    /* fall back */
    return rb_io_fsync(io);
}

#filenoInteger Also known as: to_i

Returns the integer file descriptor for the stream:

$stdin.fileno             # => 0
$stdout.fileno            # => 1
$stderr.fileno            # => 2
File.open('t.txt').fileno # => 10
f.close

Returns:



2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
# File 'io.c', line 2886

static VALUE
rb_io_fileno(VALUE io)
{
    rb_io_t *fptr = RFILE(io)->fptr;
    int fd;

    rb_io_check_closed(fptr);
    fd = fptr->fd;
    return INT2FIX(fd);
}

#flushself

Flushes data buffered in self to the operating system (but does not necessarily flush data buffered in the operating system):

$stdout.print 'no newline' # Not necessarily flushed.
$stdout.flush              # Flushed.

Returns:

  • (self)


2405
2406
2407
2408
2409
# File 'io.c', line 2405

VALUE
rb_io_flush(VALUE io)
{
    return rb_io_flush_raw(io, 1);
}

#fsync0

Immediately writes to disk all data buffered in the stream, via the operating system’s fsync(2).

Note this difference:

  • IO#sync=: Ensures that data is flushed from the stream’s internal buffers, but does not guarantee that the operating system actually writes the data to disk.

  • IO#fsync: Ensures both that data is flushed from internal buffers, and that data is written to disk.

Raises an exception if the operating system does not support fsync(2).

Returns:

  • (0)


2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
# File 'io.c', line 2800

static VALUE
rb_io_fsync(VALUE io)
{
    rb_io_t *fptr;

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    if (io_fflush(fptr) < 0)
        rb_sys_fail_on_write(fptr);

    if ((int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
        rb_sys_fail_path(fptr->pathv);

    return INT2FIX(0);
}

#getbyteInteger?

Reads and returns the next byte (in range 0..255) from the stream; returns nil if already at end-of-stream. See Byte IO.

f = File.open('t.txt')
f.getbyte # => 70
f.close
f = File.open('t.rus')
f.getbyte # => 209
f.close

Related: IO#readbyte (may raise EOFError).

Returns:



5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
# File 'io.c', line 5077

VALUE
rb_io_getbyte(VALUE io)
{
    rb_io_t *fptr;
    int c;

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    READ_CHECK(fptr);
    VALUE r_stdout = rb_ractor_stdout();
    if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(r_stdout, T_FILE)) {
        rb_io_t *ofp;
        GetOpenFile(r_stdout, ofp);
        if (ofp->mode & FMODE_TTY) {
            rb_io_flush(r_stdout);
        }
    }
    if (io_fillbuf(fptr) < 0) {
        return Qnil;
    }
    fptr->rbuf.off++;
    fptr->rbuf.len--;
    c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
    return INT2FIX(c & 0xff);
}

#getcnil

Reads and returns the next 1-character string from the stream; returns nil if already at end-of-stream. See Character IO.

f = File.open('t.txt')
f.getc     # => "F"
f.close
f = File.open('t.rus')
f.getc.ord # => 1090
f.close

Related: IO#readchar (may raise EOFError).

Returns:

  • (nil)


5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
# File 'io.c', line 5015

static VALUE
rb_io_getc(VALUE io)
{
    rb_io_t *fptr;
    rb_encoding *enc;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);

    enc = io_input_encoding(fptr);
    READ_CHECK(fptr);
    return io_getc(fptr, enc);
}

#gets(sep = $/, chomp: false) ⇒ String? #gets(limit, chomp: false) ⇒ String? #gets(sep, limit, chomp: false) ⇒ String?

Reads and returns a line from the stream; assigns the return value to $_. See Line IO.

With no arguments given, returns the next line as determined by line separator $/, or nil if none:

f = File.open('t.txt')
f.gets # => "First line\n"
$_     # => "First line\n"
f.gets # => "\n"
f.gets # => "Fourth line\n"
f.gets # => "Fifth line\n"
f.gets # => nil
f.close

With only string argument sep given, returns the next line as determined by line separator sep, or nil if none; see Line Separator:

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

The two special values for sep are honored:

f = File.new('t.txt')
# Get all.
f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
f.rewind
# Get paragraph (up to two line separators).
f.gets('')  # => "First line\nSecond line\n\n"
f.close

With only integer argument limit given, limits the number of bytes in the line; see Line Limit:

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

With arguments sep and limit given, combines the two behaviors (see Line Separator and Line Limit).

Optional keyword argument chomp specifies whether line separators are to be omitted:

f = File.open('t.txt')
# Chomp the lines.
f.gets(chomp: true) # => "First line"
f.gets(chomp: true) # => "Second line"
f.gets(chomp: true) # => ""
f.gets(chomp: true) # => "Fourth line"
f.gets(chomp: true) # => "Fifth line"
f.gets(chomp: true) # => nil
f.close

Overloads:

  • #gets(sep = $/, chomp: false) ⇒ String?

    Returns:

  • #gets(limit, chomp: false) ⇒ String?

    Returns:

  • #gets(sep, limit, chomp: false) ⇒ String?

    Returns:



4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
# File 'io.c', line 4388

static VALUE
rb_io_gets_m(int argc, VALUE *argv, VALUE io)
{
    VALUE str;

    str = rb_io_getline(argc, argv, io);
    rb_lastline_set(str);

    return str;
}

#initialize_copy(io) ⇒ Object

:nodoc:



8552
8553
8554
8555
8556
8557
8558
8559
8560
8561
8562
8563
8564
8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587
8588
8589
8590
8591
8592
8593
# File 'io.c', line 8552

static VALUE
rb_io_init_copy(VALUE dest, VALUE io)
{
    rb_io_t *fptr, *orig;
    int fd;
    VALUE write_io;
    rb_off_t pos;

    io = rb_io_get_io(io);
    if (!OBJ_INIT_COPY(dest, io)) return dest;
    GetOpenFile(io, orig);
    MakeOpenFile(dest, fptr);

    rb_io_flush(io);

    /* copy rb_io_t structure */
    fptr->mode = orig->mode & ~FMODE_EXTERNAL;
    fptr->encs = orig->encs;
    fptr->pid = orig->pid;
    fptr->lineno = orig->lineno;
    fptr->timeout = orig->timeout;
    if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
    fptr_copy_finalizer(fptr, orig);

    fd = ruby_dup(orig->fd);
    fptr->fd = fd;
    pos = io_tell(orig);
    if (0 <= pos)
        io_seek(fptr, pos, SEEK_SET);
    if (fptr->mode & FMODE_BINMODE) {
        rb_io_binmode(dest);
    }

    write_io = GetWriteIO(io);
    if (io != write_io) {
        write_io = rb_obj_dup(write_io);
        fptr->tied_io_for_writing = write_io;
        rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
    }

    return dest;
}

#inspectString

Returns a string representation of self:

f = File.open('t.txt')
f.inspect # => "#<File:t.txt>"
f.close

Returns:



2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
# File 'io.c', line 2994

static VALUE
rb_io_inspect(VALUE obj)
{
    rb_io_t *fptr;
    VALUE result;
    static const char closed[] = " (closed)";

    fptr = RFILE(obj)->fptr;
    if (!fptr) return rb_any_to_s(obj);
    result = rb_str_new_cstr("#<");
    rb_str_append(result, rb_class_name(CLASS_OF(obj)));
    rb_str_cat2(result, ":");
    if (NIL_P(fptr->pathv)) {
        if (fptr->fd < 0) {
            rb_str_cat(result, closed+1, strlen(closed)-1);
        }
        else {
            rb_str_catf(result, "fd %d", fptr->fd);
        }
    }
    else {
        rb_str_append(result, fptr->pathv);
        if (fptr->fd < 0) {
            rb_str_cat(result, closed, strlen(closed));
        }
    }
    return rb_str_cat2(result, ">");
}

#internal_encodingEncoding?

Returns the Encoding object that represents the encoding of the internal string, if conversion is specified, or nil otherwise.

See Encodings.

Returns:



13475
13476
13477
13478
13479
13480
13481
13482
# File 'io.c', line 13475

static VALUE
rb_io_internal_encoding(VALUE io)
{
    rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;

    if (!fptr->encs.enc2) return Qnil;
    return rb_enc_from_encoding(io_read_encoding(fptr));
}

#ioctl(integer_cmd, argument) ⇒ Integer

Invokes Posix system call ioctl(2), which issues a low-level command to an I/O device.

Issues a low-level command to an I/O device. The arguments and returned value are platform-dependent. The effect of the call is platform-dependent.

If argument argument is an integer, it is passed directly; if it is a string, it is interpreted as a binary sequence of bytes.

Not implemented on all platforms.

Returns:



11463
11464
11465
11466
11467
11468
11469
11470
# File 'io.c', line 11463

static VALUE
rb_io_ioctl(int argc, VALUE *argv, VALUE io)
{
    VALUE req, arg;

    rb_scan_args(argc, argv, "11", &req, &arg);
    return rb_ioctl(io, req, arg);
}

#isattyBoolean

Returns true if the stream is associated with a terminal device (tty), false otherwise:

f = File.new('t.txt').isatty    #=> false
f.close
f = File.new('/dev/tty').isatty #=> true
f.close

Returns:

  • (Boolean)


5293
5294
5295
5296
5297
5298
5299
5300
# File 'io.c', line 5293

static VALUE
rb_io_isatty(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    return RBOOL(isatty(fptr->fd) != 0);
}

#linenoInteger

Returns the current line number for the stream; see Line Number.

Returns:



4408
4409
4410
4411
4412
4413
4414
4415
4416
# File 'io.c', line 4408

static VALUE
rb_io_lineno(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    return INT2NUM(fptr->lineno);
}

#lineno=(integer) ⇒ Integer

Sets and returns the line number for the stream; see Line Number.

Returns:



4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
# File 'io.c', line 4427

static VALUE
rb_io_set_lineno(VALUE io, VALUE lineno)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    fptr->lineno = NUM2INT(lineno);
    return lineno;
}

#pathString?

Returns the path associated with the IO, or nil if there is no path associated with the IO. It is not guaranteed that the path exists on the filesystem.

$stdin.path # => "<STDIN>"

File.open("testfile") {|f| f.path} # => "testfile"

Returns:



2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
# File 'io.c', line 2971

VALUE
rb_io_path(VALUE io)
{
    rb_io_t *fptr = RFILE(io)->fptr;

    if (!fptr)
        return Qnil;

    return rb_obj_dup(fptr->pathv);
}

#pidInteger?

Returns the process ID of a child process associated with the stream, which will have been set by IO#popen, or nil if the stream was not created by IO#popen:

pipe = IO.popen("-")
if pipe
  $stderr.puts "In parent, child pid is #{pipe.pid}"
else
  $stderr.puts "In child, pid is #{$$}"
end

Output:

In child, pid is 26209
In parent, child pid is 26209

Returns:



2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
# File 'io.c', line 2947

static VALUE
rb_io_pid(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (!fptr->pid)
        return Qnil;
    return PIDT2NUM(fptr->pid);
}

#tellInteger

Returns the current position (in bytes) in self (see Position):

f = File.open('t.txt')
f.tell # => 0
f.gets # => "First line\n"
f.tell # => 12
f.close

Related: IO#pos=, IO#seek.

Returns:



2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
# File 'io.c', line 2427

static VALUE
rb_io_tell(VALUE io)
{
    rb_io_t *fptr;
    rb_off_t pos;

    GetOpenFile(io, fptr);
    pos = io_tell(fptr);
    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
    pos -= fptr->rbuf.len;
    return OFFT2NUM(pos);
}

#pos=(new_position) ⇒ Object

Seeks to the given new_position (in bytes); see Position:

f = File.open('t.txt')
f.tell     # => 0
f.pos = 20 # => 20
f.tell     # => 20
f.close

Related: IO#seek, IO#tell.



2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
# File 'io.c', line 2551

static VALUE
rb_io_set_pos(VALUE io, VALUE offset)
{
    rb_io_t *fptr;
    rb_off_t pos;

    pos = NUM2OFFT(offset);
    GetOpenFile(io, fptr);
    pos = io_seek(fptr, pos, SEEK_SET);
    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);

    return OFFT2NUM(pos);
}

#pread(maxlen, offset) ⇒ String #pread(maxlen, offset, out_string) ⇒ String

Behaves like IO#readpartial, except that it:

  • Reads at the given offset (in bytes).

  • Disregards, and does not modify, the stream’s position (see Position).

  • Bypasses any user space buffering in the stream.

Because this method does not disturb the stream’s state (its position, in particular), pread allows multiple threads and processes to use the same IO object for reading at various offsets.

f = File.open('t.txt')
f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
f.pos  # => 52
# Read 12 bytes at offset 0.
f.pread(12, 0) # => "First line\n"
# Read 9 bytes at offset 8.
f.pread(9, 8)  # => "ne\nSecon"
f.close

Not available on some platforms.

Overloads:



6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
# File 'io.c', line 6225

static VALUE
rb_io_pread(int argc, VALUE *argv, VALUE io)
{
    VALUE len, offset, str;
    rb_io_t *fptr;
    ssize_t n;
    struct prdwr_internal_arg arg;
    int shrinkable;

    rb_scan_args(argc, argv, "21", &len, &offset, &str);
    arg.count = NUM2SIZET(len);
    arg.offset = NUM2OFFT(offset);

    shrinkable = io_setstrbuf(&str, (long)arg.count);
    if (arg.count == 0) return str;
    arg.buf = RSTRING_PTR(str);

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);

    arg.io = fptr;
    arg.fd = fptr->fd;
    rb_io_check_closed(fptr);

    rb_str_locktmp(str);
    n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);

    if (n < 0) {
        rb_sys_fail_path(fptr->pathv);
    }
    io_set_read_length(str, n, shrinkable);
    if (n == 0 && arg.count > 0) {
        rb_eof_error();
    }

    return str;
}

Writes the given objects to the stream; returns nil. Appends the output record separator $OUTPUT_RECORD_SEPARATOR ($\), if it is not nil. See Line IO.

With argument objects given, for each object:

  • Converts via its method to_s if not a string.

  • Writes to the stream.

  • If not the last object, writes the output field separator $OUTPUT_FIELD_SEPARATOR ($,) if it is not nil.

With default separators:

f = File.open('t.tmp', 'w+')
objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
p $OUTPUT_RECORD_SEPARATOR
p $OUTPUT_FIELD_SEPARATOR
f.print(*objects)
f.rewind
p f.read
f.close

Output:

nil
nil
"00.00/10+0izerozero"

With specified separators:

$\ = "\n"
$, = ','
f.rewind
f.print(*objects)
f.rewind
p f.read

Output:

"0,0.0,0/1,0+0i,zero,zero\n"

With no argument given, writes the content of $_ (which is usually the most recent user input):

f = File.open('t.tmp', 'w+')
gets # Sets $_ to the most recent user input.
f.print
f.close

Returns:

  • (nil)


8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
8742
8743
8744
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
# File 'io.c', line 8732

VALUE
rb_io_print(int argc, const VALUE *argv, VALUE out)
{
    int i;
    VALUE line;

    /* if no argument given, print `$_' */
    if (argc == 0) {
        argc = 1;
        line = rb_lastline_get();
        argv = &line;
    }
    if (argc > 1 && !NIL_P(rb_output_fs)) {
        rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
    }
    for (i=0; i<argc; i++) {
        if (!NIL_P(rb_output_fs) && i>0) {
            rb_io_write(out, rb_output_fs);
        }
        rb_io_write(out, argv[i]);
    }
    if (argc > 0 && !NIL_P(rb_output_rs)) {
        rb_io_write(out, rb_output_rs);
    }

    return Qnil;
}

#printf(format_string, *objects) ⇒ nil

Formats and writes objects to the stream.

For details on format_string, see Format Specifications.

Returns:

  • (nil)


8606
8607
8608
8609
8610
8611
# File 'io.c', line 8606

VALUE
rb_io_printf(int argc, const VALUE *argv, VALUE out)
{
    rb_io_write(out, rb_f_sprintf(argc, argv));
    return Qnil;
}

#putc(object) ⇒ Object

Writes a character to the stream. See Character IO.

If object is numeric, converts to integer if necessary, then writes the character whose code is the least significant byte; if object is a string, writes the first character:

$stdout.putc "A"
$stdout.putc 65

Output:

AA

Returns:



8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
# File 'io.c', line 8837

static VALUE
rb_io_putc(VALUE io, VALUE ch)
{
    VALUE str;
    if (RB_TYPE_P(ch, T_STRING)) {
        str = rb_str_substr(ch, 0, 1);
    }
    else {
        char c = NUM2CHR(ch);
        str = rb_str_new(&c, 1);
    }
    rb_io_write(io, str);
    return ch;
}

#puts(*objects) ⇒ nil

Writes the given objects to the stream, which must be open for writing; returns nil.\ Writes a newline after each that does not already end with a newline sequence. If called without arguments, writes a newline. See Line IO.

Note that each added newline is the character "\n"<//tt>, not the output record separator (<tt>$\).

Treatment for each object:

  • String: writes the string.

  • Neither string nor array: writes object.to_s.

  • Array: writes each element of the array; arrays may be nested.

To keep these examples brief, we define this helper method:

def show(*objects)
  # Puts objects to file.
  f = File.new('t.tmp', 'w+')
  f.puts(objects)
  # Return file content.
  f.rewind
  p f.read
  f.close
end

# Strings without newlines.
show('foo', 'bar', 'baz')     # => "foo\nbar\nbaz\n"
# Strings, some with newlines.
show("foo\n", 'bar', "baz\n") # => "foo\nbar\nbaz\n"

# Neither strings nor arrays:
show(0, 0.0, Rational(0, 1), Complex(9, 0), :zero)
# => "0\n0.0\n0/1\n9+0i\nzero\n"

# Array of strings.
show(['foo', "bar\n", 'baz']) # => "foo\nbar\nbaz\n"
# Nested arrays.
show([[[0, 1], 2, 3], 4, 5])  # => "0\n1\n2\n3\n4\n5\n"

Returns:

  • (nil)


8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
8979
8980
8981
8982
8983
8984
8985
8986
8987
8988
8989
8990
8991
8992
8993
8994
8995
8996
8997
8998
8999
9000
9001
9002
# File 'io.c', line 8964

VALUE
rb_io_puts(int argc, const VALUE *argv, VALUE out)
{
    VALUE line, args[2];

    /* if no argument given, print newline. */
    if (argc == 0) {
        rb_io_write(out, rb_default_rs);
        return Qnil;
    }
    for (int i = 0; i < argc; i++) {
        // Convert the argument to a string:
        if (RB_TYPE_P(argv[i], T_STRING)) {
            line = argv[i];
        }
        else if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
            continue;
        }
        else {
            line = rb_obj_as_string(argv[i]);
        }

        // Write the line:
        int n = 0;
        if (RSTRING_LEN(line) == 0) {
            args[n++] = rb_default_rs;
        }
        else {
            args[n++] = line;
            if (!rb_str_end_with_asciichar(line, '\n')) {
                args[n++] = rb_default_rs;
            }
        }

        rb_io_writev(out, n, args);
    }

    return Qnil;
}

#pwrite(object, offset) ⇒ Integer

Behaves like IO#write, except that it:

  • Writes at the given offset (in bytes).

  • Disregards, and does not modify, the stream’s position (see Position).

  • Bypasses any user space buffering in the stream.

Because this method does not disturb the stream’s state (its position, in particular), pwrite allows multiple threads and processes to use the same IO object for writing at various offsets.

f = File.open('t.tmp', 'w+')
# Write 6 bytes at offset 3.
f.pwrite('ABCDEF', 3) # => 6
f.rewind
f.read # => "\u0000\u0000\u0000ABCDEF"
f.close

Not available on some platforms.

Returns:



6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
# File 'io.c', line 6306

static VALUE
rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
{
    rb_io_t *fptr;
    ssize_t n;
    struct prdwr_internal_arg arg;
    VALUE tmp;

    if (!RB_TYPE_P(str, T_STRING))
        str = rb_obj_as_string(str);

    arg.offset = NUM2OFFT(offset);

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);

    arg.io = fptr;
    arg.fd = fptr->fd;

    tmp = rb_str_tmp_frozen_acquire(str);
    arg.buf = RSTRING_PTR(tmp);
    arg.count = (size_t)RSTRING_LEN(tmp);

    n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg, RUBY_IO_WRITABLE);
    if (n < 0) rb_sys_fail_path(fptr->pathv);
    rb_str_tmp_frozen_release(str, tmp);

    return SSIZET2NUM(n);
}

#read(maxlen = nil, out_string = nil) ⇒ nil

Reads bytes from the stream; the stream must be opened for reading (see Access Modes):

  • If maxlen is nil, reads all bytes using the stream’s data mode.

  • Otherwise reads up to maxlen bytes in binary mode.

Returns a string (either a new string or the given out_string) containing the bytes read. The encoding of the string depends on both maxLen and out_string:

  • maxlen is nil: uses internal encoding of self (regardless of whether out_string was given).

  • maxlen not nil:

    • out_string given: encoding of out_string not modified.

    • out_string not given: ASCII-8BIT is used.

Without Argument out_string

When argument out_string is omitted, the returned value is a new string:

f = File.new('t.txt')
f.read
# => "First line\nSecond line\n\nFourth line\nFifth line\n"
f.rewind
f.read(30) # => "First line\r\nSecond line\r\n\r\nFou"
f.read(30) # => "rth line\r\nFifth line\r\n"
f.read(30) # => nil
f.close

If maxlen is zero, returns an empty string.

With Argument out_string

When argument out_string is given, the returned value is out_string, whose content is replaced:

f = File.new('t.txt')
s = 'foo'      # => "foo"
f.read(nil, s) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
s              # => "First line\nSecond line\n\nFourth line\nFifth line\n"
f.rewind
s = 'bar'
f.read(30, s)  # => "First line\r\nSecond line\r\n\r\nFou"
s              # => "First line\r\nSecond line\r\n\r\nFou"
s = 'baz'
f.read(30, s)  # => "rth line\r\nFifth line\r\n"
s              # => "rth line\r\nFifth line\r\n"
s = 'bat'
f.read(30, s)  # => nil
s              # => ""
f.close

Note that this method behaves like the fread() function in C. This means it retries to invoke read(2) system calls to read data with the specified maxlen (or until EOF).

This behavior is preserved even if the stream is in non-blocking mode. (This method is non-blocking-flag insensitive as other methods.)

If you need the behavior like a single read(2) system call, consider #readpartial, #read_nonblock, and #sysread.

Related: IO#write.

Returns:

  • (nil)


3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
# File 'io.c', line 3802

static VALUE
io_read(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    long n, len;
    VALUE length, str;
    int shrinkable;
#if RUBY_CRLF_ENVIRONMENT
    int previous_mode;
#endif

    rb_scan_args(argc, argv, "02", &length, &str);

    if (NIL_P(length)) {
        GetOpenFile(io, fptr);
        rb_io_check_char_readable(fptr);
        return read_all(fptr, remain_size(fptr), str);
    }
    len = NUM2LONG(length);
    if (len < 0) {
        rb_raise(rb_eArgError, "negative length %ld given", len);
    }

    shrinkable = io_setstrbuf(&str,len);

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    if (len == 0) {
        io_set_read_length(str, 0, shrinkable);
        return str;
    }

    READ_CHECK(fptr);
#if RUBY_CRLF_ENVIRONMENT
    previous_mode = set_binary_mode_with_seek_cur(fptr);
#endif
    n = io_fread(str, 0, len, fptr);
    io_set_read_length(str, n, shrinkable);
#if RUBY_CRLF_ENVIRONMENT
    if (previous_mode == O_TEXT) {
        setmode(fptr->fd, O_TEXT);
    }
#endif
    if (n == 0) return Qnil;

    return str;
}

#readbyteInteger

Reads and returns the next byte (in range 0..255) from the stream; raises EOFError if already at end-of-stream. See Byte IO.

f = File.open('t.txt')
f.readbyte # => 70
f.close
f = File.open('t.rus')
f.readbyte # => 209
f.close

Related: IO#getbyte (will not raise EOFError).

Returns:



5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
# File 'io.c', line 5122

static VALUE
rb_io_readbyte(VALUE io)
{
    VALUE c = rb_io_getbyte(io);

    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}

#readcharString

Reads and returns the next 1-character string from the stream; raises EOFError if already at end-of-stream. See Character IO.

f = File.open('t.txt')
f.readchar     # => "F"
f.close
f = File.open('t.rus')
f.readchar.ord # => 1090
f.close

Related: IO#getc (will not raise EOFError).

Returns:



5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
# File 'io.c', line 5048

static VALUE
rb_io_readchar(VALUE io)
{
    VALUE c = rb_io_getc(io);

    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}

#readlines(sep = $/, chomp: false) ⇒ Array #readlines(limit, chomp: false) ⇒ Array #readlines(sep, limit, chomp: false) ⇒ Array

Reads and returns all remaining line from the stream; does not modify $_. See Line IO.

With no arguments given, returns lines as determined by line separator $/, or nil if none:

f = File.new('t.txt')
f.readlines
# => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
f.readlines # => []
f.close

With only string argument sep given, returns lines as determined by line separator sep, or nil if none; see Line Separator:

f = File.new('t.txt')
f.readlines('li')
# => ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]
f.close

The two special values for sep are honored:

f = File.new('t.txt')
# Get all into one string.
f.readlines(nil)
# => ["First line\nSecond line\n\nFourth line\nFifth line\n"]
# Get paragraphs (up to two line separators).
f.rewind
f.readlines('')
# => ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
f.close

With only integer argument limit given, limits the number of bytes in each line; see Line Limit:

f = File.new('t.txt')
f.readlines(8)
# => ["First li", "ne\n", "Second l", "ine\n", "\n", "Fourth l", "ine\n", "Fifth li", "ne\n"]
f.close

With arguments sep and limit given, combines the two behaviors (see Line Separator and Line Limit).

Optional keyword argument chomp specifies whether line separators are to be omitted:

f = File.new('t.txt')
f.readlines(chomp: true)
# => ["First line", "Second line", "", "Fourth line", "Fifth line"]
f.close

Overloads:

  • #readlines(sep = $/, chomp: false) ⇒ Array

    Returns:

  • #readlines(limit, chomp: false) ⇒ Array

    Returns:

  • #readlines(sep, limit, chomp: false) ⇒ Array

    Returns:



4541
4542
4543
4544
4545
4546
4547
4548
# File 'io.c', line 4541

static VALUE
rb_io_readlines(int argc, VALUE *argv, VALUE io)
{
    struct getline_arg args;

    prepare_getline_args(argc, argv, &args, io);
    return io_readlines(&args, io);
}

#readpartial(maxlen) ⇒ String #readpartial(maxlen, out_string) ⇒ Object

Reads up to maxlen bytes from the stream; returns a string (either a new string or the given out_string). Its encoding is:

  • The unchanged encoding of out_string, if out_string is given.

  • ASCII-8BIT, otherwise.

  • Contains maxlen bytes from the stream, if available.

  • Otherwise contains all available bytes, if any available.

  • Otherwise is an empty string.

With the single non-negative integer argument maxlen given, returns a new string:

f = File.new('t.txt')
f.readpartial(20) # => "First line\nSecond l"
f.readpartial(20) # => "ine\n\nFourth line\n"
f.readpartial(20) # => "Fifth line\n"
f.readpartial(20) # Raises EOFError.
f.close

With both argument maxlen and string argument out_string given, returns modified out_string:

f = File.new('t.txt')
s = 'foo'
f.readpartial(20, s) # => "First line\nSecond l"
s = 'bar'
f.readpartial(0, s)  # => ""
f.close

This method is useful for a stream such as a pipe, a socket, or a tty. It blocks only when no data is immediately available. This means that it blocks only when all of the following are true:

  • The byte buffer in the stream is empty.

  • The content of the stream is empty.

  • The stream is not at EOF.

When blocked, the method waits for either more data or EOF on the stream:

  • If more data is read, the method returns the data.

  • If EOF is reached, the method raises EOFError.

When not blocked, the method responds immediately:

  • Returns data from the buffer if there is any.

  • Otherwise returns data from the stream if there is any.

  • Otherwise raises EOFError if the stream has reached EOF.

Note that this method is similar to sysread. The differences are:

  • If the byte buffer is not empty, read from the byte buffer instead of “sysread for buffered IO (IOError)”.

  • It doesn’t cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retries the system call.

The latter means that readpartial is non-blocking-flag insensitive. It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.

Examples:

#                        # Returned      Buffer Content    Pipe Content
r, w = IO.pipe           #
w << 'abc'               #               ""                "abc".
r.readpartial(4096)      # => "abc"      ""                ""
r.readpartial(4096)      # (Blocks because buffer and pipe are empty.)

#                        # Returned      Buffer Content    Pipe Content
r, w = IO.pipe           #
w << 'abc'               #               ""                "abc"
w.close                  #               ""                "abc" EOF
r.readpartial(4096)      # => "abc"      ""                 EOF
r.readpartial(4096)      # raises EOFError

#                        # Returned      Buffer Content    Pipe Content
r, w = IO.pipe           #
w << "abc\ndef\n"        #               ""                "abc\ndef\n"
r.gets                   # => "abc\n"    "def\n"           ""
w << "ghi\n"             #               "def\n"           "ghi\n"
r.readpartial(4096)      # => "def\n"    ""                "ghi\n"
r.readpartial(4096)      # => "ghi\n"    ""                ""

Overloads:



3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
# File 'io.c', line 3618

static VALUE
io_readpartial(int argc, VALUE *argv, VALUE io)
{
    VALUE ret;

    ret = io_getpartial(argc, argv, io, Qnil, 0);
    if (NIL_P(ret))
        rb_eof_error();
    return ret;
}

#reopen(other_io) ⇒ self #reopen(path, mode = 'r', **opts) ⇒ self

Reassociates the stream with another stream, which may be of a different class. This method may be used to redirect an existing stream to a new destination.

With argument other_io given, reassociates with that stream:

# Redirect $stdin from a file.
f = File.open('t.txt')
$stdin.reopen(f)
f.close

# Redirect $stdout to a file.
f = File.open('t.tmp', 'w')
$stdout.reopen(f)
f.close

With argument path given, reassociates with a new stream to that file path:

$stdin.reopen('t.txt')
$stdout.reopen('t.tmp', 'w')

Optional keyword arguments opts specify:

Overloads:

  • #reopen(other_io) ⇒ self

    Returns:

    • (self)
  • #reopen(path, mode = 'r', **opts) ⇒ self

    Returns:

    • (self)


8463
8464
8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
8499
8500
8501
8502
8503
8504
8505
8506
8507
8508
8509
8510
8511
8512
8513
8514
8515
8516
8517
8518
8519
8520
8521
8522
8523
8524
8525
8526
8527
8528
8529
8530
8531
8532
8533
8534
8535
8536
8537
8538
8539
8540
8541
8542
8543
8544
8545
8546
8547
8548
8549
# File 'io.c', line 8463

static VALUE
rb_io_reopen(int argc, VALUE *argv, VALUE file)
{
    VALUE fname, nmode, opt;
    int oflags;
    rb_io_t *fptr;

    if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
        VALUE tmp = rb_io_check_io(fname);
        if (!NIL_P(tmp)) {
            return io_reopen(file, tmp);
        }
    }

    FilePathValue(fname);
    rb_io_taint_check(file);
    fptr = RFILE(file)->fptr;
    if (!fptr) {
        fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
    }

    if (!NIL_P(nmode) || !NIL_P(opt)) {
        int fmode;
        struct rb_io_encoding convconfig;

        rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
        if (RUBY_IO_EXTERNAL_P(fptr) &&
            ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
            (fptr->mode & FMODE_READWRITE)) {
            rb_raise(rb_eArgError,
                     "%s can't change access mode from \"%s\" to \"%s\"",
                     PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
                     rb_io_fmode_modestr(fmode));
        }
        fptr->mode = fmode;
        fptr->encs = convconfig;
    }
    else {
        oflags = rb_io_fmode_oflags(fptr->mode);
    }

    fptr->pathv = fname;
    if (fptr->fd < 0) {
        fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
        fptr->stdio_file = 0;
        return file;
    }

    if (fptr->mode & FMODE_WRITABLE) {
        if (io_fflush(fptr) < 0)
            rb_sys_fail_on_write(fptr);
    }
    fptr->rbuf.off = fptr->rbuf.len = 0;

    if (fptr->stdio_file) {
        int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
                           rb_io_oflags_modestr(oflags),
                           fptr->stdio_file);
        if (e) rb_syserr_fail_path(e, fptr->pathv);
        fptr->fd = fileno(fptr->stdio_file);
        rb_fd_fix_cloexec(fptr->fd);
#ifdef USE_SETVBUF
        if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
            rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
#endif
        if (fptr->stdio_file == stderr) {
            if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
                rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
        }
        else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
            if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
                rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
        }
    }
    else {
        int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
        int err = 0;
        if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
            err = errno;
        (void)close(tmpfd);
        if (err) {
            rb_syserr_fail_path(err, fptr->pathv);
        }
    }

    return file;
}

#rewind0

Repositions the stream to its beginning, setting both the position and the line number to zero; see Position and Line Number:

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

Note that this method cannot be used with streams such as pipes, ttys, and sockets.

Returns:

  • (0)


2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
# File 'io.c', line 2591

static VALUE
rb_io_rewind(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
    if (io == ARGF.current_file) {
        ARGF.lineno -= fptr->lineno;
    }
    fptr->lineno = 0;
    if (fptr->readconv) {
        clear_readconv(fptr);
    }

    return INT2FIX(0);
}

#seek(offset, whence = IO::SEEK_SET) ⇒ 0

Seeks to the position given by integer offset (see Position) and constant whence, which is one of:

  • :CUR or IO::SEEK_CUR: Repositions the stream to its current position plus the given offset:

    f = File.open('t.txt')
    f.tell            # => 0
    f.seek(20, :CUR)  # => 0
    f.tell            # => 20
    f.seek(-10, :CUR) # => 0
    f.tell            # => 10
    f.close
    
  • :END or IO::SEEK_END: Repositions the stream to its end plus the given offset:

    f = File.open('t.txt')
    f.tell            # => 0
    f.seek(0, :END)   # => 0  # Repositions to stream end.
    f.tell            # => 52
    f.seek(-20, :END) # => 0
    f.tell            # => 32
    f.seek(-40, :END) # => 0
    f.tell            # => 12
    f.close
    
  • :SET or IO:SEEK_SET: Repositions the stream to the given offset:

    f = File.open('t.txt')
    f.tell            # => 0
    f.seek(20, :SET) # => 0
    f.tell           # => 20
    f.seek(40, :SET) # => 0
    f.tell           # => 40
    f.close
    

Related: IO#pos=, IO#tell.

Returns:

  • (0)


2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
# File 'io.c', line 2521

static VALUE
rb_io_seek_m(int argc, VALUE *argv, VALUE io)
{
    VALUE offset, ptrname;
    int whence = SEEK_SET;

    if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
        whence = interpret_seek_whence(ptrname);
    }

    return rb_io_seek(io, offset, whence);
}

#set_encoding(ext_enc) ⇒ self #set_encoding(ext_enc, int_enc, **enc_opts) ⇒ self #set_encoding('ext_enc: int_enc', **enc_opts) ⇒ self

See Encodings.

Argument ext_enc, if given, must be an Encoding object or a String with the encoding name; it is assigned as the encoding for the stream.

Argument int_enc, if given, must be an Encoding object or a String with the encoding name; it is assigned as the encoding for the internal string.

Argument 'ext_enc:int_enc', if given, is a string containing two colon-separated encoding names; corresponding Encoding objects are assigned as the external and internal encodings for the stream.

If the external encoding of a string is binary/ASCII-8BIT, the internal encoding of the string is set to nil, since no transcoding is needed.

Optional keyword arguments enc_opts specify Encoding options.

Overloads:

  • #set_encoding(ext_enc) ⇒ self

    Returns:

    • (self)
  • #set_encoding(ext_enc, int_enc, **enc_opts) ⇒ self

    Returns:

    • (self)
  • #set_encoding('ext_enc: int_enc', **enc_opts) ⇒ self

    Returns:

    • (self)


13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
# File 'io.c', line 13514

static VALUE
rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    VALUE v1, v2, opt;

    if (!RB_TYPE_P(io, T_FILE)) {
        return forward(io, id_set_encoding, argc, argv);
    }

    argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
    GetOpenFile(io, fptr);
    io_encoding_set(fptr, v1, v2, opt);
    return io;
}

#set_encoding_by_bomEncoding?

If the stream begins with a BOM (byte order marker), consumes the BOM and sets the external encoding accordingly; returns the result encoding if found, or nil otherwise:

File.write('t.tmp', "\u{FEFF}abc")
io = File.open('t.tmp', 'rb')
io.set_encoding_by_bom # => #<Encoding:UTF-8>
io.close

File.write('t.tmp', 'abc')
io = File.open('t.tmp', 'rb')
io.set_encoding_by_bom # => nil
io.close

Raises an exception if the stream is not binmode or its encoding has already been set.

Returns:



9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
# File 'io.c', line 9596

static VALUE
rb_io_set_encoding_by_bom(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (!(fptr->mode & FMODE_BINMODE)) {
        rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
    }
    if (fptr->encs.enc2) {
        rb_raise(rb_eArgError, "encoding conversion is set");
    }
    else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
        rb_raise(rb_eArgError, "encoding is set to %s already",
                 rb_enc_name(fptr->encs.enc));
    }
    if (!io_set_encoding_by_bom(io)) return Qnil;
    return rb_enc_from_encoding(fptr->encs.enc);
}

#statObject

Returns status information for ios as an object of type File::Stat.

f = File.new("testfile")
s = f.stat
"%o" % s.mode   #=> "100644"
s.blksize       #=> 4096
s.atime         #=> Wed Apr 09 08:53:54 CDT 2003


1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
# File 'file.c', line 1364

static VALUE
rb_io_stat(VALUE obj)
{
    rb_io_t *fptr;
    struct stat st;

    GetOpenFile(obj, fptr);
    if (fstat(fptr->fd, &st) == -1) {
        rb_sys_fail_path(fptr->pathv);
    }
    return rb_stat_new(&st);
}

#syncBoolean

Returns the current sync mode of the stream. When sync mode is true, all output is immediately flushed to the underlying operating system and is not buffered by Ruby internally. See also #fsync.

f = File.open('t.tmp', 'w')
f.sync # => false
f.sync = true
f.sync # => true
f.close

Returns:

  • (Boolean)


2729
2730
2731
2732
2733
2734
2735
2736
2737
# File 'io.c', line 2729

static VALUE
rb_io_sync(VALUE io)
{
    rb_io_t *fptr;

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    return RBOOL(fptr->mode & FMODE_SYNC);
}

#sync=(sync) ⇒ Object



2819
2820
2821
2822
2823
2824
# File 'io.c', line 2819

static VALUE
rb_io_set_sync(VALUE io, VALUE sync)
{
    rb_notimplement();
    UNREACHABLE;
}

#sysread(maxlen) ⇒ String #sysread(maxlen, out_string) ⇒ String

Behaves like IO#readpartial, except that it uses low-level system functions.

This method should not be used with other stream-reader methods.

Overloads:



6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
# File 'io.c', line 6117

static VALUE
rb_io_sysread(int argc, VALUE *argv, VALUE io)
{
    VALUE len, str;
    rb_io_t *fptr;
    long n, ilen;
    struct io_internal_read_struct iis;
    int shrinkable;

    rb_scan_args(argc, argv, "11", &len, &str);
    ilen = NUM2LONG(len);

    shrinkable = io_setstrbuf(&str, ilen);
    if (ilen == 0) return str;

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);

    if (READ_DATA_BUFFERED(fptr)) {
        rb_raise(rb_eIOError, "sysread for buffered IO");
    }

    rb_io_check_closed(fptr);

    io_setstrbuf(&str, ilen);
    iis.th = rb_thread_current();
    iis.fptr = fptr;
    iis.nonblock = 0;
    iis.fd = fptr->fd;
    iis.buf = RSTRING_PTR(str);
    iis.capa = ilen;
    iis.timeout = NULL;
    n = io_read_memory_locktmp(str, &iis);

    if (n < 0) {
        rb_sys_fail_path(fptr->pathv);
    }

    io_set_read_length(str, n, shrinkable);

    if (n == 0 && ilen > 0) {
        rb_eof_error();
    }

    return str;
}

#sysseek(offset, whence = IO::SEEK_SET) ⇒ Integer

Behaves like IO#seek, except that it:

  • Uses low-level system functions.

  • Returns the new position.

Returns:



6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
# File 'io.c', line 6033

static VALUE
rb_io_sysseek(int argc, VALUE *argv, VALUE io)
{
    VALUE offset, ptrname;
    int whence = SEEK_SET;
    rb_io_t *fptr;
    rb_off_t pos;

    if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
        whence = interpret_seek_whence(ptrname);
    }
    pos = NUM2OFFT(offset);
    GetOpenFile(io, fptr);
    if ((fptr->mode & FMODE_READABLE) &&
        (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
        rb_raise(rb_eIOError, "sysseek for buffered IO");
    }
    if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
        rb_warn("sysseek for buffered IO");
    }
    errno = 0;
    pos = lseek(fptr->fd, pos, whence);
    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);

    return OFFT2NUM(pos);
}

#syswrite(object) ⇒ Integer

Writes the given object to self, which must be opened for writing (see Modes); returns the number bytes written. If object is not a string is converted via method to_s:

f = File.new('t.tmp', 'w')
f.syswrite('foo') # => 3
f.syswrite(30)    # => 2
f.syswrite(:foo)  # => 3
f.close

This methods should not be used with other stream-writer methods.

Returns:



6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
# File 'io.c', line 6078

static VALUE
rb_io_syswrite(VALUE io, VALUE str)
{
    VALUE tmp;
    rb_io_t *fptr;
    long n, len;
    const char *ptr;

    if (!RB_TYPE_P(str, T_STRING))
        str = rb_obj_as_string(str);

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);

    if (fptr->wbuf.len) {
        rb_warn("syswrite for buffered IO");
    }

    tmp = rb_str_tmp_frozen_acquire(str);
    RSTRING_GETMEM(tmp, ptr, len);
    n = rb_io_write_memory(fptr, ptr, len);
    if (n < 0) rb_sys_fail_path(fptr->pathv);
    rb_str_tmp_frozen_release(str, tmp);

    return LONG2FIX(n);
}

#tellInteger

Returns the current position (in bytes) in self (see Position):

f = File.open('t.txt')
f.tell # => 0
f.gets # => "First line\n"
f.tell # => 12
f.close

Related: IO#pos=, IO#seek.

Returns:



2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
# File 'io.c', line 2427

static VALUE
rb_io_tell(VALUE io)
{
    rb_io_t *fptr;
    rb_off_t pos;

    GetOpenFile(io, fptr);
    pos = io_tell(fptr);
    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
    pos -= fptr->rbuf.len;
    return OFFT2NUM(pos);
}

#timeoutnil

Get the internal timeout duration or nil if it was not set.

Returns:

  • (nil)


856
857
858
859
860
861
862
# File 'io.c', line 856

VALUE
rb_io_timeout(VALUE self)
{
    rb_io_t *fptr = rb_io_get_fptr(self);

    return fptr->timeout;
}

#timeout=(duration) ⇒ Object #timeout=(nil) ⇒ nil

Sets the internal timeout to the specified duration or nil. The timeout applies to all blocking operations where possible.

When the operation performs longer than the timeout set, IO::TimeoutError is raised.

This affects the following methods (but is not limited to): #gets, #puts, #read, #write, #wait_readable and #wait_writable. This also affects blocking socket operations like Socket#accept and Socket#connect.

Some operations like File#open and IO#close are not affected by the timeout. A timeout during a write operation may leave the IO in an inconsistent state, e.g. data was partially written. Generally speaking, a timeout is a last ditch effort to prevent an application from hanging on slow I/O operations, such as those that occur during a slowloris attack.

Overloads:

  • #timeout=(nil) ⇒ nil

    Returns:

    • (nil)


885
886
887
888
889
890
891
892
893
894
895
896
897
898
# File 'io.c', line 885

VALUE
rb_io_set_timeout(VALUE self, VALUE timeout)
{
    // Validate it:
    if (RTEST(timeout)) {
        rb_time_interval(timeout);
    }

    rb_io_t *fptr = rb_io_get_fptr(self);

    fptr->timeout = timeout;

    return self;
}

#to_ioself

Returns self.

Returns:

  • (self)


3031
3032
3033
3034
3035
# File 'io.c', line 3031

static VALUE
rb_io_to_io(VALUE io)
{
    return io;
}

#pathString?

Returns the path associated with the IO, or nil if there is no path associated with the IO. It is not guaranteed that the path exists on the filesystem.

$stdin.path # => "<STDIN>"

File.open("testfile") {|f| f.path} # => "testfile"

Returns:



2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
# File 'io.c', line 2971

VALUE
rb_io_path(VALUE io)
{
    rb_io_t *fptr = RFILE(io)->fptr;

    if (!fptr)
        return Qnil;

    return rb_obj_dup(fptr->pathv);
}

#isattyBoolean

Returns true if the stream is associated with a terminal device (tty), false otherwise:

f = File.new('t.txt').isatty    #=> false
f.close
f = File.new('/dev/tty').isatty #=> true
f.close

Returns:

  • (Boolean)


5293
5294
5295
5296
5297
5298
5299
5300
# File 'io.c', line 5293

static VALUE
rb_io_isatty(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    return RBOOL(isatty(fptr->fd) != 0);
}

#ungetbyte(integer) ⇒ nil #ungetbyte(string) ⇒ nil

Pushes back (“unshifts”) the given data onto the stream’s buffer, placing the data so that it is next to be read; returns nil. See Byte IO.

Note that:

  • Calling the method has no effect with unbuffered reads (such as IO#sysread).

  • Calling #rewind on the stream discards the pushed-back data.

When argument integer is given, uses only its low-order byte:

File.write('t.tmp', '012')
f = File.open('t.tmp')
f.ungetbyte(0x41)   # => nil
f.read              # => "A012"
f.rewind
f.ungetbyte(0x4243) # => nil
f.read              # => "C012"
f.close

When argument string is given, uses all bytes:

File.write('t.tmp', '012')
f = File.open('t.tmp')
f.ungetbyte('A')    # => nil
f.read              # => "A012"
f.rewind
f.ungetbyte('BCDE') # => nil
f.read              # => "BCDE012"
f.close

Overloads:

  • #ungetbyte(integer) ⇒ nil

    Returns:

    • (nil)
  • #ungetbyte(string) ⇒ nil

    Returns:

    • (nil)


5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
# File 'io.c', line 5171

VALUE
rb_io_ungetbyte(VALUE io, VALUE b)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    switch (TYPE(b)) {
      case T_NIL:
        return Qnil;
      case T_FIXNUM:
      case T_BIGNUM: ;
        VALUE v = rb_int_modulo(b, INT2FIX(256));
        unsigned char c = NUM2INT(v) & 0xFF;
        b = rb_str_new((const char *)&c, 1);
        break;
      default:
        StringValue(b);
    }
    io_ungetbyte(b, fptr);
    return Qnil;
}

#ungetc(integer) ⇒ nil #ungetc(string) ⇒ nil

Pushes back (“unshifts”) the given data onto the stream’s buffer, placing the data so that it is next to be read; returns nil. See Character IO.

Note that:

  • Calling the method has no effect with unbuffered reads (such as IO#sysread).

  • Calling #rewind on the stream discards the pushed-back data.

When argument integer is given, interprets the integer as a character:

File.write('t.tmp', '012')
f = File.open('t.tmp')
f.ungetc(0x41)     # => nil
f.read             # => "A012"
f.rewind
f.ungetc(0x0442)   # => nil
f.getc.ord         # => 1090
f.close

When argument string is given, uses all characters:

File.write('t.tmp', '012')
f = File.open('t.tmp')
f.ungetc('A')      # => nil
f.read      # => "A012"
f.rewind
f.ungetc("\u0442\u0435\u0441\u0442") # => nil
f.getc.ord      # => 1090
f.getc.ord      # => 1077
f.getc.ord      # => 1089
f.getc.ord      # => 1090
f.close

Overloads:

  • #ungetc(integer) ⇒ nil

    Returns:

    • (nil)
  • #ungetc(string) ⇒ nil

    Returns:

    • (nil)


5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
# File 'io.c', line 5235

VALUE
rb_io_ungetc(VALUE io, VALUE c)
{
    rb_io_t *fptr;
    long len;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    if (FIXNUM_P(c)) {
        c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
    }
    else if (RB_BIGNUM_TYPE_P(c)) {
        c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
    }
    else {
        StringValue(c);
    }
    if (NEED_READCONV(fptr)) {
        SET_BINARY_MODE(fptr);
        len = RSTRING_LEN(c);
#if SIZEOF_LONG > SIZEOF_INT
        if (len > INT_MAX)
            rb_raise(rb_eIOError, "ungetc failed");
#endif
        make_readconv(fptr, (int)len);
        if (fptr->cbuf.capa - fptr->cbuf.len < len)
            rb_raise(rb_eIOError, "ungetc failed");
        if (fptr->cbuf.off < len) {
            MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
                    fptr->cbuf.ptr+fptr->cbuf.off,
                    char, fptr->cbuf.len);
            fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
        }
        fptr->cbuf.off -= (int)len;
        fptr->cbuf.len += (int)len;
        MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
    }
    else {
        NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
        io_ungetbyte(c, fptr);
    }
    return Qnil;
}

#wait(events, timeout) ⇒ false? #wait(timeout = nil, mode = :read) ⇒ self, ...

Waits until the IO becomes ready for the specified events and returns the subset of events that become ready, or a falsy value when times out.

The events can be a bit mask of IO::READABLE, IO::WRITABLE or IO::PRIORITY.

Returns an event mask (truthy value) immediately when buffered data is available.

Optional parameter mode is one of :read, :write, or :read_write.

Overloads:

  • #wait(events, timeout) ⇒ false?

    Returns:

    • (false, nil)
  • #wait(timeout = nil, mode = :read) ⇒ self, ...

    Returns:

    • (self, true, false)


9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919
9920
9921
9922
9923
9924
9925
9926
9927
9928
9929
9930
9931
9932
9933
9934
9935
9936
9937
9938
9939
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
# File 'io.c', line 9906

static VALUE
io_wait(int argc, VALUE *argv, VALUE io)
{
    VALUE timeout = Qundef;
    enum rb_io_event events = 0;
    int return_io = 0;

    // The documented signature for this method is actually incorrect.
    // A single timeout is allowed in any position, and multiple symbols can be given.
    // Whether this is intentional or not, I don't know, and as such I consider this to
    // be a legacy/slow path.
    if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
        // We'd prefer to return the actual mask, but this form would return the io itself:
        return_io = 1;

        // Slow/messy path:
        for (int i = 0; i < argc; i += 1) {
            if (RB_SYMBOL_P(argv[i])) {
                events |= wait_mode_sym(argv[i]);
            }
            else if (UNDEF_P(timeout)) {
                rb_time_interval(timeout = argv[i]);
            }
            else {
                rb_raise(rb_eArgError, "timeout given more than once");
            }
        }

        if (UNDEF_P(timeout)) timeout = Qnil;

        if (events == 0) {
            events = RUBY_IO_READABLE;
        }
    }
    else /* argc == 2 and neither are symbols */ {
        // This is the fast path:
        events = io_event_from_value(argv[0]);
        timeout = argv[1];
    }

    if (events & RUBY_IO_READABLE) {
        rb_io_t *fptr = NULL;
        RB_IO_POINTER(io, fptr);

        if (rb_io_read_pending(fptr)) {
            // This was the original behaviour:
            if (return_io) return Qtrue;
            // New behaviour always returns an event mask:
            else return RB_INT2NUM(RUBY_IO_READABLE);
        }
    }

    return io_wait_event(io, events, timeout, return_io);
}

#wait_priorityObject #wait_priority(timeout) ⇒ Object

Waits until IO is priority and returns a truthy value or a falsy value when times out. Priority data is sent and received using the Socket::MSG_OOB flag and is typically limited to streams.



9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
# File 'io.c', line 9829

static VALUE
io_wait_priority(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr = NULL;

    RB_IO_POINTER(io, fptr);
    rb_io_check_readable(fptr);

    if (rb_io_read_pending(fptr)) return Qtrue;

    rb_check_arity(argc, 0, 1);
    VALUE timeout = argc == 1 ? argv[0] : Qnil;

    return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
}

#wait_readableObject #wait_readable(timeout) ⇒ Object

Waits until IO is readable and returns a truthy value, or a falsy value when times out. Returns a truthy value immediately when buffered data is available.



9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
# File 'io.c', line 9782

static VALUE
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;

    RB_IO_POINTER(io, fptr);
    rb_io_check_readable(fptr);

    if (rb_io_read_pending(fptr)) return Qtrue;

    rb_check_arity(argc, 0, 1);
    VALUE timeout = (argc == 1 ? argv[0] : Qnil);

    return io_wait_event(io, RUBY_IO_READABLE, timeout, 1);
}

#wait_writableObject #wait_writable(timeout) ⇒ Object

Waits until IO is writable and returns a truthy value or a falsy value when times out.



9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
# File 'io.c', line 9806

static VALUE
io_wait_writable(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;

    RB_IO_POINTER(io, fptr);
    rb_io_check_writable(fptr);

    rb_check_arity(argc, 0, 1);
    VALUE timeout = (argc == 1 ? argv[0] : Qnil);

    return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
}

#write(*objects) ⇒ Integer

Writes each of the given objects to self, which must be opened for writing (see Access Modes); returns the total number bytes written; each of objects that is not a string is converted via method to_s:

$stdout.write('Hello', ', ', 'World!', "\n") # => 14
$stdout.write('foo', :bar, 2, "\n")          # => 8

Output:

Hello, World!
foobar2

Related: IO#read.

Returns:



2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
# File 'io.c', line 2289

static VALUE
io_write_m(int argc, VALUE *argv, VALUE io)
{
    if (argc != 1) {
        return io_writev(argc, argv, io);
    }
    else {
        VALUE str = argv[0];
        return io_write(io, str, 0);
    }
}