class IO - RDoc Documentation

# class IO

Expect library adds the `IO` instance method `expect`, which does similar act to tcl’s expect extension.

In order to use this method, you must require expect:

    require 'expect'

Please see `expect` for usage.

The `IO` class is the basis for all input and output in Ruby. An I/O stream may be duplexed (that is, bidirectional), and so may use more than one native operating system stream.

Many of the examples in this section use the `File` class, the only standard subclass of `IO`. The two classes are closely associated. Like the `File` class, the `Socket` library subclasses from `IO` (such as `TCPSocket` or `UDPSocket`).

The `Kernel#open` method can create an `IO` (or `File`) object for these types of arguments:

- A plain string represents a filename suitable for the underlying operating system.

- A string starting with `"|"` indicates a subprocess. The remainder of the string following the `"|"` is invoked as a process with appropriate input/output channels connected to it.

- A string equal to `"|-"` will create another Ruby instance as a subprocess.

The `IO` may be opened with different file modes (read-only, write-only) and encodings for proper conversion. See `IO.new` for these options. See `Kernel#open` for details of the various command formats described above.

`IO.popen`, the `Open3` library, or Process#spawn may also be used to communicate with subprocesses through an `IO`.

Ruby will convert pathnames between different operating system conventions if possible. For instance, on a Windows system the filename `"/gumby/ruby/test.rb"` will be opened as `"\gumby\ruby\test.rb"`. When specifying a Windows-style filename in a Ruby string, remember to escape the backslashes:

    "C:\\gumby\\ruby\\test.rb"

Our examples here will use the Unix-style forward slashes; File::ALT_SEPARATOR can be used to get the platform-specific separator character.

The global constant `ARGF` (also accessible as `$<`) provides an IO-like stream which allows access to all files mentioned on the command line (or STDIN if no files are mentioned). `ARGF#path` and its alias `ARGF#filename` are provided to access the name of the file currently being read.

## io/console¶ ↑

The io/console extension provides methods for interacting with the console. The console can be accessed from `IO.console` or the standard input/output/error `IO` objects.

Requiring io/console adds the following methods:

- `IO::console`

- `IO#raw`

- `IO#raw!`

- `IO#cooked`

- `IO#cooked!`

- `IO#getch`

- `IO#echo=`

- `IO#echo?`

- `IO#noecho`

- `IO#winsize`

- `IO#winsize=`

- `IO#iflush`

- `IO#ioflush`

- `IO#oflush`

Example:

    require 'io/console'
    rows, columns = $stdout.winsize
    puts "Your screen is #{columns} wide and #{rows} tall"

## Example Files¶ ↑

Many examples here use these filenames and their corresponding files:

- `t.txt`: A text-only file that is assumed to exist via:

      text = <<~EOT
        This is line one.
        This is the second line.
        This is the third line.
      EOT
      File.write('t.txt', text)

- `t.dat`: A data file that is assumed to exist via:

      data = "\u9990\u9991\u9992\u9993\u9994"
      f = File.open('t.dat', 'wb:UTF-16')
      f.write(data)
      f.close

- `t.rus`: A Russian-language text file that is assumed to exist via:

      File.write('t.rus', "\u{442 435 441 442}")

- `t.tmp`: A file that is assumed not to exist.

## Modes¶ ↑

A number of IO method calls must or may specify a mode for the stream; the mode determines how stream is to be accessible, including:

- Whether the stream is to be read-only, write-only, or read-write.

- Whether the stream is positioned at its beginning or its end.

- Whether the stream treats data as text-only or binary.

- The external and internal encodings.

### Mode Specified as an Integer¶ ↑

When `mode` is an integer it must be one or more (combined by bitwise OR (`|`) of the modes defined in `File::Constants`:

- `File::RDONLY`: Open for reading only.

- `File::WRONLY`: Open for writing only.

- `File::RDWR`: Open for reading and writing.

- `File::APPEND`: Open for appending only.

- `File::CREAT`: Create file if it does not exist.

- `File::EXCL`: Raise an exception if `File::CREAT` is given and the file exists.

Examples:

    File.new('t.txt', File::RDONLY)
    File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)

Note: `Method` `IO#set_encoding` does not allow the mode to be specified as an integer.

### Mode Specified As a String¶ ↑

When `mode` is a string it must begin with one of the following:

- `'r'`: Read-only stream, positioned at the beginning; the stream cannot be changed to writable.

- `'w'`: Write-only stream, positioned at the beginning; the stream cannot be changed to readable.

- `'a'`: Write-only stream, positioned at the end; every write appends to the end; the stream cannot be changed to readable.

- `'r+'`: Read-write stream, positioned at the beginning.

- `'w+'`: Read-write stream, positioned at the end.

- `'a+'`: Read-write stream, positioned at the end.

For a writable file stream (that is, any except read-only), the file is truncated to zero if it exists, and is created if it does not exist.

Examples:

    File.open('t.txt', 'r')
    File.open('t.tmp', 'w')

Either of the following may be suffixed to any of the above:

- `'t'`: Text data; sets the default external encoding to `Encoding::UTF_8`; on Windows, enables conversion between EOL and CRLF.

- `'b'`: Binary data; sets the default external encoding to `Encoding::ASCII_8BIT`; on Windows, suppresses conversion between EOL and CRLF.

If neither is given, the stream defaults to text data.

Examples:

    File.open('t.txt', 'rt')
    File.open('t.dat', 'rb')

The following may be suffixed to any writable mode above:

- `'x'`: Creates the file if it does not exist; raises an exception if the file exists.

Example:

    File.open('t.tmp', 'wx')

Finally, the mode string may specify encodings – either external encoding only or both external and internal encodings – by appending one or both encoding names, separated by colons:

    f = File.new('t.dat', 'rb')
    f.external_encoding # => #<Encoding:ASCII-8BIT>
    f.internal_encoding # => nil
    f = File.new('t.dat', 'rb:UTF-16')
    f.external_encoding # => #<Encoding:UTF-16 (dummy)>
    f.internal_encoding # => nil
    f = File.new('t.dat', 'rb:UTF-16:UTF-16')
    f.external_encoding # => #<Encoding:UTF-16 (dummy)>
    f.internal_encoding # => #<Encoding:UTF-16>

The numerous encoding names are available in array `Encoding.name_list`:

    Encoding.name_list.size    # => 175
    Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]

## Encodings¶ ↑

When the external encoding is set, strings read are tagged by that encoding when reading, and strings written are converted to that encoding when writing.

When both external and internal encodings are set, strings read are converted from external to internal encoding, and strings written are converted from internal to external encoding. For further details about transcoding input and output, see `Encoding`.

If the external encoding is `'BOM|UTF-8'`, `'BOM|UTF-16LE'` or `'BOM|UTF16-BE'`, Ruby checks for a Unicode BOM in the input document to help determine the encoding. For UTF-16 encodings the file open mode must be binary. If the BOM is found, it is stripped and the external encoding from the BOM is used.

Note that the BOM-style encoding option is case insensitive, so ‘bom|utf-8’ is also valid.)

## Open Options¶ ↑

A number of IO methods accept an optional parameter `opts`, which determines 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.

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

## Getline Options¶ ↑

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

- `:chomp`: If `true`, line separators are omitted; default is `false`.

## Position¶ ↑

An IO stream has a position, which is the non-negative integer offset (in bytes) in the stream where the next read or write will occur.

Note that a text stream may have multi-byte characters, so a text stream whose position is `n` (bytes) may not have `n` characters preceding the current position – there may be fewer.

A new stream is initially positioned:

- At the beginning (position `0`) if its mode is `'r'`, `'w'`, or `'r+'`.

- At the end (position `self.size`) if its mode is `'a'`, `'w+'`, or `'a+'`.

Methods to query the position:

- `IO#tell` and its alias `IO#pos` return the position for an open stream.

- `IO#eof?` and its alias `IO#eof` return whether the position is at the end of a readable stream.

Reading from a stream usually changes its position:

    f = File.open('t.txt')
    f.tell     # => 0
    f.readline # => "This is line one.\n"
    f.tell     # => 19
    f.readline # => "This is the second line.\n"
    f.tell     # => 45
    f.eof?     # => false
    f.readline # => "Here's the third line.\n"
    f.eof?     # => true

Writing to a stream usually changes its position:

    f = File.open('t.tmp', 'w')
    f.tell         # => 0
    f.write('foo') # => 3
    f.tell         # => 3
    f.write('bar') # => 3
    f.tell         # => 6

Iterating over a stream usually changes its position:

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

Output:

    "position=19 eof?=false line=This is line one.\n"
    "position=45 eof?=false line=This is the second line.\n"
    "position=70 eof?=true line=This is the third line.\n"

The position may also be changed by certain other methods:

- `IO#pos=` and `IO#seek` change the position to a specified offset.

- `IO#rewind` changes the position to the beginning.

## Line Number¶ ↑

A readable IO stream has a line number, which is the non-negative integer line number in the stream where the next read will occur.

A new stream is initially has line number `0`.

Method `IO#lineno` returns the line number.

Reading lines from a stream usually changes its line number:

    f = File.open('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

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

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

Output:

    "position=19 eof?=false line=This is line one.\n"
    "position=45 eof?=false line=This is the second line.\n"
    "position=70 eof?=true line=This is the third line.\n"

## What’s Here¶ ↑

First, what’s elsewhere. Class IO:

- Inherits from class Object.

- Includes module Enumerable, which provides dozens of additional methods.

Here, class IO provides methods that are useful for:

- Creating

- Reading

- Writing

- Positioning

- Iterating

- Settings

- Querying

- Buffering

- Low-Level Access

- Other

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

- `readchar`

    Returns the next character read from `self`; same as `getc`, but raises an exception on end-of-file.

- `readline`

    Returns the next line read from `self`; same as getline, but raises an exception of end-of-file.

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

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

### Constants

EWOULDBLOCKWaitReadable

  `EAGAINWaitReadable`

EWOULDBLOCKWaitWritable

  `EAGAINWaitWritable`

PRIORITY
READABLE
SEEK_CUR

  `Set` I/O position from the current position

SEEK_DATA

  `Set` I/O position to the next location containing data

SEEK_END

  `Set` I/O position from the end

SEEK_HOLE

  `Set` I/O position to the next hole

SEEK_SET

  `Set` I/O position from the beginning

WRITABLE

### Public Class Methods

binread(name, [length [, offset]]) → string click to toggle source
binread(name, [length [, offset]]) → string

Opens the file, optionally seeks to the given offset, then returns length bytes (defaulting to the rest of the file). binread ensures the file is closed before returning. The open mode would be `"rb:ASCII-8BIT"`.

If `name` starts with a pipe character (`"|"`) and the receiver is the `IO` class, a subprocess is created in the same way as `Kernel#open`, and its output is returned. Consider to use `File.binread` to disable the behavior of subprocess invocation.

    File.binread("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
    File.binread("testfile", 20)       #=> "This is line one\nThi"
    File.binread("testfile", 20, 10)   #=> "ne one\nThis is line "
    IO.binread("| cat testfile")       #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"

See also `IO.read` for details about `name` and open_args.

    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
        };
        convconfig_t 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(name, string, [offset]) → integer click to toggle source
binwrite(name, string, [offset], open_args) → integer
binwrite(name, string, [offset]) → integer
binwrite(name, string, [offset], open_args) → integer

Same as `IO.write` except opening the file in binary mode and ASCII-8BIT encoding (`"wb:ASCII-8BIT"`).

If `name` starts with a pipe character (`"|"`) and the receiver is the `IO` class, a subprocess is created in the same way as `Kernel#open`, and its output is returned. Consider to use `File.binwrite` to disable the behavior of subprocess invocation.

See also `IO.read` for details about `name` and open_args.

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

console → #<File:/dev/tty> click to toggle source
console(sym, *args)

Returns an `File` instance opened console.

If `sym` is given, it will be sent to the opened console with `args` and the result will be returned instead of the console `IO` itself.

You must require ‘io/console’ to use this method.

    static VALUE
    console_dev(int argc, VALUE *argv, VALUE klass)
    {
        VALUE con = 0;
        rb_io_t *fptr;
        VALUE sym = 0;

        rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS);
        if (argc) {
            Check_Type(sym = argv[0], T_SYMBOL);
        }
        if (klass == rb_cIO) klass = rb_cFile;
        if (rb_const_defined(klass, id_console)) {
            con = rb_const_get(klass, id_console);
            if (!RB_TYPE_P(con, T_FILE) ||
                (!(fptr = RFILE(con)->fptr) || GetReadFD(fptr) == -1)) {
                rb_const_remove(klass, id_console);
                con = 0;
            }
        }
        if (sym) {
            if (sym == ID2SYM(id_close) && argc == 1) {
                if (con) {
                    rb_io_close(con);
                    rb_const_remove(klass, id_console);
                    con = 0;
                }
                return Qnil;
            }
        }
        if (!con) {
            VALUE args[2];
    #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
    # define CONSOLE_DEVICE "/dev/tty"
    #elif defined _WIN32
    # define CONSOLE_DEVICE "con$"
    # define CONSOLE_DEVICE_FOR_READING "conin$"
    # define CONSOLE_DEVICE_FOR_WRITING "conout$"
    #endif
    #ifndef CONSOLE_DEVICE_FOR_READING
    # define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
    #endif
    #ifdef CONSOLE_DEVICE_FOR_WRITING
            VALUE out;
            rb_io_t *ofptr;
    #endif
            int fd;

    #ifdef CONSOLE_DEVICE_FOR_WRITING
            fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0);
            if (fd < 0) return Qnil;
            rb_update_max_fd(fd);
            args[1] = INT2FIX(O_WRONLY);
            args[0] = INT2NUM(fd);
            out = rb_class_new_instance(2, args, klass);
    #endif
            fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_READING, O_RDWR, 0);
            if (fd < 0) {
    #ifdef CONSOLE_DEVICE_FOR_WRITING
                rb_io_close(out);
    #endif
                return Qnil;
            }
            rb_update_max_fd(fd);
            args[1] = INT2FIX(O_RDWR);
            args[0] = INT2NUM(fd);
            con = rb_class_new_instance(2, args, klass);
            GetOpenFile(con, fptr);
            fptr->pathv = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
    #ifdef CONSOLE_DEVICE_FOR_WRITING
            GetOpenFile(out, ofptr);
            ofptr->pathv = fptr->pathv;
            fptr->tied_io_for_writing = out;
            ofptr->mode |= FMODE_SYNC;
    #endif
            fptr->mode |= FMODE_SYNC;
            rb_const_set(klass, id_console, con);
        }
        if (sym) {
            return rb_f_send(argc, argv, con);
        }
        return con;
    }

console_size()
Alias for: default_console_size
copy_stream(src, dst) click to toggle source
copy_stream(src, dst, copy_length)
copy_stream(src, dst, copy_length, src_offset)

`IO.copy_stream` copies src to dst. src and dst is either a filename or an IO-like object. IO-like object for src should have `readpartial` or `read` method. IO-like object for dst should have `write` method. (Specialized mechanisms, such as sendfile system call, may be used on appropriate situation.)

This method returns the number of bytes copied.

If optional arguments are not given, the start position of the copy is the beginning of the filename or the current file offset of the `IO`. The end position of the copy is the end of file.

If copy_length is given, No more than copy_length bytes are copied.

If src_offset is given, it specifies the start position of the copy.

When src_offset is specified and src is an `IO`, `IO.copy_stream` doesn’t move the current file offset.

    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 = (off_t)-1;
        else
            st.copy_length = NUM2OFFT(length);

        if (NIL_P(src_offset))
            st.src_offset = (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);
    }

default_console_size() click to toggle source

fallback to console window size

    # File ext/io/console/lib/console/size.rb, line 3
    def IO.default_console_size
      [
        ENV["LINES"].to_i.nonzero? || 25,
        ENV["COLUMNS"].to_i.nonzero? || 80,
      ]
    end

Also aliased as: console_size
for_fd(fd, mode [, opt]) → io click to toggle source

Synonym for `IO.new`.

    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(name, sep=$/ [, getline_args, open_args]) {|line| block } → nil click to toggle source
foreach(name, limit [, getline_args, open_args]) {|line| block } → nil
foreach(name, sep, limit [, getline_args, open_args]) {|line| block } → nil
foreach(...) → an_enumerator
foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } → nil
foreach(name, limit [, getline_args, open_args]) {|line| block } → nil
foreach(name, sep, limit [, getline_args, open_args]) {|line| block } → nil
foreach(...) → an_enumerator

Executes the block for every line in the named I/O port, where lines are separated by sep.

If no block is given, an enumerator is returned instead.

If `name` starts with a pipe character (`"|"`) and the receiver is the `IO` class, a subprocess is created in the same way as `Kernel#open`, and its output is returned. Consider to use `File.foreach` to disable the behavior of subprocess invocation.

    File.foreach("testfile") {|x| print "GOT ", x }
    IO.foreach("| cat testfile") {|x| print "GOT ", x }

produces:

    GOT This is line one
    GOT This is line two
    GOT This is line three
    GOT And so on...

If the last argument is a hash, it’s the keyword argument to open. See `IO.readlines` for details about getline_args. And see also `IO.read` for details about open_args.

    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, "13:", NULL, 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(fd [, mode] [, opt]) → io click to toggle source

Returns a new `IO` object (a stream) for the given integer file descriptor `fd` and `mode` string. `opt` may be used to specify parts of `mode` in a more readable fashion. See also `IO.sysopen` and `IO.for_fd`.

`IO.new` is called by various `File` and `IO` opening methods such as `IO::open`, `Kernel#open`, and `File::open`.

### Open Mode¶ ↑

When `mode` is an integer it must be combination of the modes defined in `File::Constants` (`File::RDONLY`, `File::WRONLY|File::CREAT`). See the open(2) man page for more information.

When `mode` is a string it must be in one of the following forms:

    fmode
    fmode ":" ext_enc
    fmode ":" ext_enc ":" int_enc
    fmode ":" "BOM|UTF-*"

`fmode` is an `IO` open mode string, `ext_enc` is the external encoding for the `IO` and `int_enc` is the internal encoding.

#### `IO` Open Mode¶ ↑

Ruby allows the following open modes:

    "r"  Read-only, starts at beginning of file  (default mode).

    "r+" Read-write, starts at beginning of file.

    "w"  Write-only, truncates existing file
         to zero length or creates a new file for writing.

    "w+" Read-write, truncates existing file to zero length
         or creates a new file for reading and writing.

    "a"  Write-only, each write call appends data at end of file.
         Creates a new file for writing if file does not exist.

    "a+" Read-write, each write call appends data at end of file.
         Creates a new file for reading and writing if file does
         not exist.

The following modes must be used separately, and along with one or more of the modes seen above.

    "b"  Binary file mode
         Suppresses EOL <-> CRLF conversion on Windows. And
         sets external encoding to ASCII-8BIT unless explicitly
         specified.

    "t"  Text file mode

The exclusive access mode (“x”) can be used together with “w” to ensure the file is created. Errno::EEXIST is raised when it already exists. It may not be supported with all kinds of streams (e.g. pipes).

When the open mode of original `IO` is read only, the mode cannot be changed to be writable. Similarly, the open mode cannot be changed from write only to readable.

When such a change is attempted the error is raised in different locations according to the platform.

### `IO` `Encoding`¶ ↑

When `ext_enc` is specified, strings read will be tagged by the encoding when reading, and strings output will be converted to the specified encoding when writing.

When `ext_enc` and `int_enc` are specified read strings will be converted from `ext_enc` to `int_enc` upon input, and written strings will be converted from `int_enc` to `ext_enc` upon output. See `Encoding` for further details of transcoding on input and output.

If “BOM|UTF-8”, “BOM|UTF-16LE” or “BOM|UTF16-BE” are used, Ruby checks for a Unicode BOM in the input document to help determine the encoding. For UTF-16 encodings the file open mode must be binary. When present, the BOM is stripped and the external encoding from the BOM is used. When the BOM is missing the given Unicode encoding is used as `ext_enc`. (The BOM-set encoding option is case insensitive, so “bom|utf-8” is also valid.)

### Options¶ ↑

`opt` can be used instead of `mode` for improved readability. The following keys are supported:

:mode

  Same as `mode` parameter

:flags

  Specifies file open flags as integer. If `mode` parameter is given, this parameter will be bitwise-ORed.

:external_encoding

  External encoding for the `IO`.

:internal_encoding

  Internal encoding for the `IO`. “-” 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 the value is truth value, same as “t” in argument `mode`.

:binmode

  If the value is truth value, same as “b” in argument `mode`.

:autoclose

  If the value is `false`, the `fd` will be kept open after this `IO` instance gets finalized.

Also, `opt` can have same keys in `String#encode` for controlling conversion between the external encoding and the internal encoding.

### Example 1¶ ↑

    fd = IO.sysopen("/dev/tty", "w")
    a = IO.new(fd,"w")
    $stderr.puts "Hello"
    a.puts "World"

Produces:

    Hello
    World

### Example 2¶ ↑

    require 'fcntl'

    fd = STDERR.fcntl(Fcntl::F_DUPFD)
    io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
    io.puts "Hello, World!"

    fd = STDERR.fcntl(Fcntl::F_DUPFD)
    io = IO.new(fd, mode: 'w', cr_newline: true,
                external_encoding: Encoding::UTF_16LE)
    io.puts "Hello, World!"

Both of above print “Hello, World!” in UTF-16LE to standard error output with converting EOL generated by `puts` to CR.

    static VALUE
    rb_io_initialize(int argc, VALUE *argv, VALUE io)
    {
        VALUE fnum, vmode;
        rb_io_t *fp;
        int fd, fmode, oflags = O_RDONLY;
        convconfig_t convconfig;
        VALUE opt;
    #if defined(HAVE_FCNTL) && defined(F_GETFL)
        int ofmode;
    #else
        struct stat st;
    #endif

        argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
        rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);

        fd = NUM2INT(fnum);
        if (rb_reserved_fd_p(fd)) {
            rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
        }
    #if defined(HAVE_FCNTL) && defined(F_GETFL)
        oflags = fcntl(fd, F_GETFL);
        if (oflags == -1) rb_sys_fail(0);
    #else
        if (fstat(fd, &st) < 0) rb_sys_fail(0);
    #endif
        rb_update_max_fd(fd);
    #if defined(HAVE_FCNTL) && defined(F_GETFL)
        ofmode = rb_io_oflags_fmode(oflags);
        if (NIL_P(vmode)) {
            fmode = ofmode;
        }
        else if ((~ofmode & fmode) & FMODE_READWRITE) {
            VALUE error = INT2FIX(EINVAL);
            rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
        }
    #endif
        if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
            fmode |= FMODE_PREP;
        }
        MakeOpenFile(io, fp);
        fp->self = io;
        fp->fd = fd;
        fp->mode = fmode;
        fp->encs = convconfig;
        clear_codeconv(fp);
        io_check_tty(fp);
        if (fileno(stdin) == fd)
            fp->stdio_file = stdin;
        else if (fileno(stdout) == fd)
            fp->stdio_file = stdout;
        else if (fileno(stderr) == fd)
            fp->stdio_file = stderr;

        if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
        return io;
    }

open(fd, mode="r" [, opt]) → io click to toggle source
open(fd, mode="r" [, opt]) {|io| block } → obj

With no associated block, `IO.open` is a synonym for `IO.new`. If the optional code block is given, it will be passed `io` as an argument, and the `IO` object will automatically be closed when the block terminates. In this instance, `IO.open` returns the value of the block.

See `IO.new` for a description of the `fd`, `mode` and `opt` parameters.

    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 → [read_io, write_io] click to toggle source
pipe(ext_enc) → [read_io, write_io]
pipe("ext_enc:int_enc" [, opt]) → [read_io, write_io]
pipe(ext_enc, int_enc [, opt]) → [read_io, write_io]
pipe(...) {|read_io, write_io| ... }

Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element array of `IO` objects: `[` read_io, write_io `]`.

If a block is given, the block is called and returns the value of the block. read_io and write_io are sent to the block as arguments. If read_io and write_io are not closed when the block exits, they are closed. i.e. closing read_io and/or write_io doesn’t cause an error.

Not available on all platforms.

If an encoding (encoding name or encoding object) is specified as an optional argument, read string from pipe is tagged with the encoding specified. If the argument is a colon separated two encoding names “A:B”, the read string is converted from encoding A (external encoding) to encoding B (internal encoding), then tagged with B. If two optional arguments are specified, those must be encoding objects or encoding names, and the first one is the external encoding, and the second one is the internal encoding. If the external encoding and the internal encoding is specified, optional hash argument specify the conversion option.

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>

    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" [, opt]) → io click to toggle source
popen([env,] cmd, mode="r" [, opt]) {|io| block } → obj

Runs the specified command as a subprocess; the subprocess’s standard input and output will be connected to the returned `IO` object.

The PID of the started process can be obtained by `IO#pid` method.

cmd is a string or an array as follows.

    cmd:
      "-"                                      : fork
      commandline                              : command line string which is passed to a shell
      [env, cmdname, arg1, ..., opts]          : command name and zero or more arguments (no shell)
      [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
    (env and opts are optional.)

If cmd is a `String` “`-`”, then a new instance of Ruby is started as the subprocess.

If cmd is an `Array` of `String`, then it will be used as the subprocess’s `argv` bypassing a shell. The array can contain a hash at first for environments and a hash at last for options similar to `spawn`.

The default mode for the new file object is “r”, but mode may be set to any of the modes listed in the description for class `IO`. The last argument opt qualifies mode.

    # 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
    # spawn option.  See the document of Kernel.spawn.
    IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
      ls_result_with_error = ls_io.read
    }

    # spawn options can be mixed with IO options
    IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
      ls_result_with_error = ls_io.read
    }

Raises exceptions which `IO.pipe` and `Kernel.spawn` raise.

If a block is given, Ruby will run the command as a child connected to Ruby with a pipe. Ruby’s end of the pipe will be passed as a parameter to the block. At the end of block, Ruby closes the pipe and sets `$?`. In this case `IO.popen` returns the value of the block.

If a block is given with a cmd of “`-`”, the block will be run in two separate processes: once in the parent, and once in a child. The parent process will be passed the pipe object as a parameter to the block, the child version of the block will be passed `nil`, and the child’s standard in and standard out will be connected to the parent through the pipe. Not available on all platforms.

    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
    }

produces:

    ["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;

    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(name, [length [, offset]] [, opt]) → string click to toggle source
read(name, [length [, offset]] [, opt]) → string

Opens the file, optionally seeks to the given `offset`, then returns `length` bytes (defaulting to the rest of the file). `read` ensures the file is closed before returning.

If `name` starts with a pipe character (`"|"`) and the receiver is the `IO` class, a subprocess is created in the same way as `Kernel#open`, and its output is returned. Consider to use `File.read` to disable the behavior of subprocess invocation.

### Options¶ ↑

The options hash accepts the following keys:

:encoding

  string or encoding

  Specifies the encoding of the read string. `:encoding` will be ignored if `length` is specified. See `Encoding.aliases` for possible encodings.

:mode

  string or integer

  Specifies the mode argument for open(). It must start with an “r”, otherwise it will cause an error. See `IO.new` for the list of possible modes.

:open_args

  array

  Specifies arguments for open() as an array. This key can not be used in combination with either `:encoding` or `:mode`.

Examples:

    File.read("testfile")            #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
    File.read("testfile", 20)        #=> "This is line one\nThi"
    File.read("testfile", 20, 10)    #=> "ne one\nThis is line "
    File.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
    IO.read("|ls -a")                #=> ".\n..\n"...

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

        argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
        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(name, sep=$/ [, getline_args, open_args]) → array click to toggle source
readlines(name, limit [, getline_args, open_args]) → array
readlines(name, sep, limit [, getline_args, open_args]) → array
readlines(name, sep=$/ [, getline_args, open_args]) → array
readlines(name, limit [, getline_args, open_args]) → array
readlines(name, sep, limit [, getline_args, open_args]) → array

Reads the entire file specified by name as individual lines, and returns those lines in an array. Lines are separated by sep.

If `name` starts with a pipe character (`"|"`) and the receiver is the `IO` class, a subprocess is created in the same way as `Kernel#open`, and its output is returned. Consider to use `File.readlines` to disable the behavior of subprocess invocation.

    a = File.readlines("testfile")
    a[0]   #=> "This is line one\n"

    b = File.readlines("testfile", chomp: true)
    b[0]   #=> "This is line one"

    IO.readlines("|ls -a")     #=> [".\n", "..\n", ...]

If the last argument is a hash, it’s the keyword argument to open.

### Options for getline¶ ↑

The options hash accepts the following keys:

:chomp

  When the optional `chomp` keyword argument has a true value, `\n`, `\r`, and `\r\n` will be removed from the end of each line.

See also `IO.read` for details about `name` and open_args.

    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, "13:", NULL, 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_array [, write_array [, error_array [, timeout]]]) → array or nil click to toggle source

Calls select(2) system call. It monitors given arrays of `IO` objects, waits until one or more of `IO` objects are ready for reading, are ready for writing, and have pending exceptions respectively, and returns an array that contains arrays of those `IO` objects. It will return `nil` if optional timeout value is given and no `IO` object is ready in timeout seconds.

`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 nonblocking 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 nonblocking 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 nonblocking 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) manual on GNU/Linux system.

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

### Parameters¶ ↑

read_array

  an array of `IO` objects that wait until ready for read

write_array

  an array of `IO` objects that wait until ready for write

error_array

  an array of `IO` objects that wait for exceptions

timeout

  a numeric value in second

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

produces:

    ping pong
    ping pong
    ping pong
    (snipped)
    ping

    static VALUE
    rb_f_select(int argc, VALUE *argv, VALUE obj)
    {
        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, [perm]]) → integer click to toggle source

Opens the given path, returning the underlying file descriptor as a `Integer`.

    IO.sysopen("testfile")   #=> 3

    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 {
            SafeStringValue(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) → new_io or nil click to toggle source

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

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

write(name, string [, offset]) → integer click to toggle source
write(name, string [, offset] [, opt]) → integer
write(name, string [, offset]) → integer
write(name, string [, offset] [, opt]) → integer

Opens the file, optionally seeks to the given offset, writes string, then returns the length written. `write` ensures the file is closed before returning. If offset is not given in write mode, the file is truncated. Otherwise, it is not truncated.

If `name` starts with a pipe character (`"|"`) and the receiver is the `IO` class, a subprocess is created in the same way as `Kernel#open`, and its output is returned. Consider to use `File.write` to disable the behavior of subprocess invocation.

    File.write("testfile", "0123456789", 20)  #=> 10
    # File could contain:  "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
    File.write("testfile", "0123456789")      #=> 10
    # File would now read: "0123456789"
    IO.write("|tr a-z A-Z", "abc")            #=> 3
    # Prints "ABC" to the standard output

If the last argument is a hash, it specifies options for the internal open(). It accepts the following keys:

:encoding

  string or encoding

  Specifies the encoding of the read string. See `Encoding.aliases` for possible encodings.

:mode

  string or integer

  Specifies the mode argument for open(). It must start with “w”, “a”, or “r+”, otherwise it will cause an error. See `IO.new` for the list of possible modes.

:perm

  integer

  Specifies the perm argument for open().

:open_args

  array

  Specifies arguments for open() as an array. This key can not be used in combination with other keys.

See also `IO.read` for details about `name` and open_args.

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

### Public Instance Methods

self << object → self click to toggle source

Writes the given `object` to `self`, which must be opened for writing (see 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

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

advise(advice, offset=0, len=0) → nil click to toggle source

Announce an intention to access data from the current file in a specific pattern. On platforms that do not support the posix_fadvise(2) system call, this method is a no-op.

advice is one of the following symbols:

:normal

  No advice to give; the default assumption for an open file.

:sequential

  The data will be accessed sequentially with lower offsets read before higher ones.

:random

  The data will be accessed in random order.

:willneed

  The data will be accessed in the near future.

:dontneed

  The data will not be accessed in the near future.

:noreuse

  The data will only be accessed once.

The semantics of a piece of advice are platform-dependent. See man 2 posix_fadvise for details.

“data” means the region of the current file that begins at offset and extends for len bytes. If len is 0, the region ends at the last byte of the file. By default, both offset and len are 0, meaning that the advice applies to the entire file.

If an error occurs, one of the following exceptions will be raised:

`IOError`

  The `IO` stream is closed.

Errno::EBADF

  The file descriptor of the current file is invalid.

Errno::EINVAL

  An invalid value for advice was given.

Errno::ESPIPE

  The file descriptor of the current file refers to a FIFO or pipe. (Linux raises Errno::EINVAL in this case).

`TypeError`

  Either advice was not a `Symbol`, or one of the other arguments was not an `Integer`.

`RangeError`

  One of the arguments given was too big/small.

This list is not exhaustive; other `Errno`

  exceptions are also possible.

    static VALUE
    rb_io_advise(int argc, VALUE *argv, VALUE io)
    {
        VALUE advice, offset, len;
        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 → true or false click to toggle source

Sets auto-close flag.

    f = open("/dev/null")
    IO.for_fd(f.fileno)
    # ...
    f.gets # may cause Errno::EBADF

    f = open("/dev/null")
    IO.for_fd(f.fileno).autoclose = false
    # ...
    f.gets # won't cause Errno::EBADF

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

autoclose? → true or false click to toggle source

Returns `true` if the underlying file descriptor of ios will be closed automatically at its finalization, otherwise `false`.

    static VALUE
    rb_io_autoclose_p(VALUE io)
    {
        rb_io_t *fptr = RFILE(io)->fptr;
        rb_io_check_closed(fptr);
        return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
    }

beep() click to toggle source

    static VALUE
    console_beep(VALUE io)
    {
        rb_io_t *fptr;
        int fd;

        GetOpenFile(io, fptr);
        fd = GetWriteFD(fptr);
    #ifdef _WIN32
        (void)fd;
        MessageBeep(0);
    #else
        if (write(fd, "\a", 1) < 0)
            sys_fail_fptr(fptr);
    #endif
        return io;
    }

binmode → ios click to toggle source

Puts ios into binary mode. Once a stream is in binary mode, it cannot be reset to nonbinary mode.

- newline conversion disabled

- encoding conversion disabled

- content is treated as ASCII-8BIT

    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? → true or false click to toggle source

Returns `true` if ios is binmode.

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

check_winsize_changed() click to toggle source

    static VALUE
    console_check_winsize_changed(VALUE io)
    {
        rb_io_t *fptr;
        HANDLE h;
        DWORD num;

        GetOpenFile(io, fptr);
        h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(fptr));
        while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) {
            INPUT_RECORD rec;
            if (ReadConsoleInput(h, &rec, 1, &num)) {
                if (rec.EventType == WINDOW_BUFFER_SIZE_EVENT) {
                    rb_yield(Qnil);
                }
            }
        }
        return io;
    }

clear_screen() click to toggle source

    static VALUE
    console_clear_screen(VALUE io)
    {
        console_erase_screen(io, INT2FIX(2));
        console_goto(io, INT2FIX(0), INT2FIX(0));
        return io;
    }

close → nil click to toggle source

Closes ios and flushes any pending writes to the operating system. The stream is unavailable for any further data operations; an `IOError` is raised if such an attempt is made. I/O streams are automatically closed when they are claimed by the garbage collector.

If ios is opened by `IO.popen`, `close` sets `$?`.

Calling this method on closed `IO` object is just ignored since Ruby 2.3.

    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 → true or false click to toggle source

Sets a close-on-exec flag.

    f = open("/dev/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.

    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? → true or false click to toggle source

Returns `true` if ios will be closed on exec.

    f = open("/dev/null")
    f.close_on_exec?                 #=> false
    f.close_on_exec = true
    f.close_on_exec?                 #=> true
    f.close_on_exec = false
    f.close_on_exec?                 #=> false

    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_read → nil click to toggle source

Closes the read end of a duplex I/O stream (i.e., one that contains both a read and a write stream, such as a pipe). Will raise an `IOError` if the stream is not duplexed.

    f = IO.popen("/bin/sh","r+")
    f.close_read
    f.readlines

produces:

    prog.rb:3:in `readlines': not opened for reading (IOError)
     from prog.rb:3

Calling this method on closed `IO` object is just ignored since Ruby 2.3.

    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_write → nil click to toggle source

Closes the write end of a duplex I/O stream (i.e., one that contains both a read and a write stream, such as a pipe). Will raise an `IOError` if the stream is not duplexed.

    f = IO.popen("/bin/sh","r+")
    f.close_write
    f.print "nowhere"

produces:

    prog.rb:3:in `write': not opened for writing (IOError)
     from prog.rb:3:in `print'
     from prog.rb:3

Calling this method on closed `IO` object is just ignored since Ruby 2.3.

    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? → true or false click to toggle source

Returns `true` if ios is completely closed (for duplex streams, both reader and writer), `false` otherwise.

    f = File.new("testfile")
    f.close         #=> nil
    f.closed?       #=> true
    f = IO.popen("/bin/sh","r+")
    f.close_write   #=> nil
    f.closed?       #=> false
    f.close_read    #=> nil
    f.closed?       #=> true

    static VALUE
    rb_io_closed(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);
    }

console_mode → mode click to toggle source

Returns a data represents the current console mode.

You must require ‘io/console’ to use this method.

    static VALUE
    console_conmode_get(VALUE io)
    {
        conmode t;
        rb_io_t *fptr;
        int fd;

        GetOpenFile(io, fptr);
        fd = GetReadFD(fptr);
        if (!getattr(fd, &t)) sys_fail_fptr(fptr);

        return conmode_new(cConmode, &t);
    }

console_mode = mode click to toggle source

Sets the console mode to `mode`.

You must require ‘io/console’ to use this method.

    static VALUE
    console_conmode_set(VALUE io, VALUE mode)
    {
        conmode *t, r;
        rb_io_t *fptr;
        int fd;

        TypedData_Get_Struct(mode, conmode, &conmode_type, t);
        r = *t;
        GetOpenFile(io, fptr);
        fd = GetReadFD(fptr);
        if (!setattr(fd, &r)) sys_fail_fptr(fptr);

        return mode;
    }

cooked {|io| } click to toggle source

Yields `self` within cooked mode.

    STDIN.cooked(&:gets)

will read and return a line with echo back and line editing.

You must require ‘io/console’ to use this method.

    static VALUE
    console_cooked(VALUE io)
    {
        return ttymode(io, rb_yield, io, set_cookedmode, NULL);
    }

cooked! click to toggle source

Enables cooked mode.

If the terminal mode needs to be back, use io.cooked { … }.

You must require ‘io/console’ to use this method.

    static VALUE
    console_set_cooked(VALUE io)
    {
        conmode t;
        rb_io_t *fptr;
        int fd;

        GetOpenFile(io, fptr);
        fd = GetReadFD(fptr);
        if (!getattr(fd, &t)) sys_fail_fptr(fptr);
        set_cookedmode(&t, NULL);
        if (!setattr(fd, &t)) sys_fail_fptr(fptr);
        return io;
    }

cursor() click to toggle source

    static VALUE
    console_cursor_pos(VALUE io)
    {
        rb_io_t *fptr;
        int fd;
        rb_console_size_t ws;

        GetOpenFile(io, fptr);
        fd = GetWriteFD(fptr);
        if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
            rb_syserr_fail(LAST_ERROR, 0);
        }
        return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X));
    }

cursor=(p1) click to toggle source

    static VALUE
    console_cursor_set(VALUE io, VALUE cpos)
    {
        cpos = rb_convert_type(cpos, T_ARRAY, "Array", "to_ary");
        if (RARRAY_LEN(cpos) != 2) rb_raise(rb_eArgError, "expected 2D coordinate");
        return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1));
    }

cursor_down(p1) click to toggle source

    static VALUE
    console_cursor_down(VALUE io, VALUE val)
    {
        return console_move(io, +NUM2INT(val), 0);
    }

cursor_left(p1) click to toggle source

    static VALUE
    console_cursor_left(VALUE io, VALUE val)
    {
        return console_move(io, 0, -NUM2INT(val));
    }

cursor_right(p1) click to toggle source

    static VALUE
    console_cursor_right(VALUE io, VALUE val)
    {
        return console_move(io, 0, +NUM2INT(val));
    }

cursor_up(p1) click to toggle source

    static VALUE
    console_cursor_up(VALUE io, VALUE val)
    {
        return console_move(io, -NUM2INT(val), 0);
    }

each(sep=$/ [, getline_args]) {|line| block } → ios click to toggle source
each(limit [, getline_args]) {|line| block } → ios
each(sep, limit [, getline_args]) {|line| block } → ios
each(...) → an_enumerator

Executes the block for every line in ios, where lines are separated by sep. ios must be opened for reading or an `IOError` will be raised.

If no block is given, an enumerator is returned instead.

    f = File.new("testfile")
    f.each {|line| puts "#{f.lineno}: #{line}" }

produces:

    1: This is line one
    2: This is line two
    3: This is line three
    4: And so on...

See `IO.readlines` for details about getline_args.

    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;
    }

Also aliased as: each_line
each_byte {|byte| block } → ios click to toggle source
each_byte → an_enumerator

Calls the given block once for each byte (0..255) in ios, passing the byte as an argument. The stream must be opened for reading or an `IOError` will be raised.

If no block is given, an enumerator is returned instead.

    f = File.new("testfile")
    checksum = 0
    f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
    checksum                           #=> 12

    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| block } → ios click to toggle source
each_char → an_enumerator

Calls the given block once for each character in ios, passing the character as an argument. The stream must be opened for reading or an `IOError` will be raised.

If no block is given, an enumerator is returned instead.

    f = File.new("testfile")
    f.each_char {|c| print c, ' ' }   #=> #<File:testfile>

    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| block } → ios click to toggle source
each_codepoint → an_enumerator

Passes the `Integer` ordinal of each character in ios, passing the codepoint as an argument. The stream must be opened for reading or an `IOError` will be raised.

If no block is given, an enumerator is returned instead.

    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(*args)

Executes the block for every line in ios, where lines are separated by sep. ios must be opened for reading or an `IOError` will be raised.

If no block is given, an enumerator is returned instead.

    f = File.new("testfile")
    f.each {|line| puts "#{f.lineno}: #{line}" }

produces:

    1: This is line one
    2: This is line two
    3: This is line three
    4: And so on...

See `IO.readlines` for details about getline_args.

Alias for: each
echo = flag click to toggle source

Enables/disables echo back. On some platforms, all combinations of this flags and raw/cooked mode may not be valid.

You must require ‘io/console’ to use this method.

    static VALUE
    console_set_echo(VALUE io, VALUE f)
    {
        conmode t;
        rb_io_t *fptr;
        int fd;

        GetOpenFile(io, fptr);
        fd = GetReadFD(fptr);
        if (!getattr(fd, &t)) sys_fail_fptr(fptr);
        if (RTEST(f))
            set_echo(&t, NULL);
        else
            set_noecho(&t, NULL);
        if (!setattr(fd, &t)) sys_fail_fptr(fptr);
        return io;
    }

echo? → true or false click to toggle source

Returns `true` if echo back is enabled.

You must require ‘io/console’ to use this method.

    static VALUE
    console_echo_p(VALUE io)
    {
        conmode t;
        rb_io_t *fptr;
        int fd;

        GetOpenFile(io, fptr);
        fd = GetReadFD(fptr);
        if (!getattr(fd, &t)) sys_fail_fptr(fptr);
        return echo_p(&t) ? Qtrue : Qfalse;
    }

eof → true or false click to toggle source

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

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

I#eof? is an alias for `IO#eof`.

    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);
    }

Also aliased as: eof?
eof?()

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

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

I#eof? is an alias for `IO#eof`.

Alias for: eof
erase_line(p1) click to toggle source

    static VALUE
    console_erase_line(VALUE io, VALUE val)
    {
        rb_io_t *fptr;
        HANDLE h;
        rb_console_size_t ws;
        COORD *pos = &ws.dwCursorPosition;
        DWORD w;
        int mode = mode_in_range(val, 2, "line erase");

        GetOpenFile(io, fptr);
        h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
        if (!GetConsoleScreenBufferInfo(h, &ws)) {
            rb_syserr_fail(LAST_ERROR, 0);
        }
        w = winsize_col(&ws);
        switch (mode) {
          case 0:                   /* after cursor */
            w -= pos->X;
            break;
          case 1:                   /* before *and* cursor */
            w = pos->X + 1;
            pos->X = 0;
            break;
          case 2:                   /* entire line */
            pos->X = 0;
            break;
        }
        constat_clear(h, ws.wAttributes, w, *pos);
        return io;
    }

erase_screen(p1) click to toggle source

    static VALUE
    console_erase_screen(VALUE io, VALUE val)
    {
        rb_io_t *fptr;
        HANDLE h;
        rb_console_size_t ws;
        COORD *pos = &ws.dwCursorPosition;
        DWORD w;
        int mode = mode_in_range(val, 3, "screen erase");

        GetOpenFile(io, fptr);
        h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
        if (!GetConsoleScreenBufferInfo(h, &ws)) {
            rb_syserr_fail(LAST_ERROR, 0);
        }
        w = winsize_col(&ws);
        switch (mode) {
          case 0:   /* erase after cursor */
            w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
            break;
          case 1:   /* erase before *and* cursor */
            w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
            pos->X = 0;
            pos->Y = ws.srWindow.Top;
            break;
          case 2:   /* erase entire screen */
            w = (w * winsize_row(&ws));
            pos->X = 0;
            pos->Y = ws.srWindow.Top;
            break;
          case 3:   /* erase entire screen */
            w = (w * ws.dwSize.Y);
            pos->X = 0;
            pos->Y = 0;
            break;
        }
        constat_clear(h, ws.wAttributes, w, *pos);
        return io;
    }

IO#expect(pattern,timeout=9999999) → Array click to toggle source
IO#expect(pattern,timeout=9999999) { |result| ... } → nil

Reads from the `IO` until the given `pattern` matches or the `timeout` is over.

It returns an array with the read buffer, followed by the matches. If a block is given, the result is yielded to the block and returns nil.

When called without a block, it waits until the input that matches the given `pattern` is obtained from the `IO` or the time specified as the timeout passes. An array is returned when the pattern is obtained from the `IO`. The first element of the array is the entire string obtained from the `IO` until the pattern matches, followed by elements indicating which the pattern which matched to the anchor in the regular expression.

The optional timeout parameter defines, in seconds, the total time to wait for the pattern. If the timeout expires or eof is found, nil is returned or yielded. However, the buffer in a timeout session is kept for the next expect call. The default timeout is 9999999 seconds.

    # File ext/pty/lib/expect.rb, line 33
    def expect(pat,timeout=9999999)
      buf = ''.dup
      case pat
      when String
        e_pat = Regexp.new(Regexp.quote(pat))
      when Regexp
        e_pat = pat
      else
        raise TypeError, "unsupported pattern class: #{pat.class}"
      end
      @unusedBuf ||= ''
      while true
        if not @unusedBuf.empty?
          c = @unusedBuf.slice!(0)
        elsif !IO.select([self],nil,nil,timeout) or eof? then
          result = nil
          @unusedBuf = buf
          break
        else
          c = getc
        end
        buf << c
        if $expect_verbose
          STDOUT.print c
          STDOUT.flush
        end
        if mat=e_pat.match(buf) then
          result = [buf,*mat.captures]
          break
        end
      end
      if block_given? then
        yield result
      else
        return result
      end
      nil
    end

external_encoding → encoding click to toggle source

Returns the `Encoding` object that represents the encoding of the file. If io is in write mode and no encoding is specified, returns `nil`.

    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, arg) → integer click to toggle source

Provides a mechanism for issuing low-level commands to control or query file-oriented I/O streams. Arguments and results are platform dependent. If arg 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). On Unix platforms, see `fcntl(2)` for details. Not implemented on all platforms.

    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);
    }

fdatasync → 0 click to toggle source

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.

    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_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
            return INT2FIX(0);

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

fileno → integer click to toggle source

Returns the integer file descriptor for the stream:

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

`IO#to_i` is an alias for `IO#fileno`.

    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);
    }

Also aliased as: to_i
flush → self click to toggle source

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.

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

fsync → 0 click to toggle source

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

    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_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
            rb_sys_fail_path(fptr->pathv);
        return INT2FIX(0);
    }

getbyte → integer or nil click to toggle source

Gets the next 8-bit byte (0..255) from ios. Returns `nil` if called at end of file.

    f = File.new("testfile")
    f.getbyte   #=> 84
    f.getbyte   #=> 104

    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);
    }

getc → string or nil click to toggle source

Reads a one-character string from ios. Returns `nil` if called at end of file.

    f = File.new("testfile")
    f.getc   #=> "h"
    f.getc   #=> "e"

    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);
    }

getch(min: nil, time: nil, intr: nil) → char click to toggle source

Reads and returns a character in raw mode.

See `IO#raw` for details on the parameters.

You must require ‘io/console’ to use this method.

    static VALUE
    console_getch(int argc, VALUE *argv, VALUE io)
    {
        rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
    #ifndef _WIN32
        return ttymode(io, getc_call, io, set_rawmode, optp);
    #else
        rb_io_t *fptr;
        VALUE str;
        wint_t c;
        int len;
        char buf[8];
        wint_t wbuf[2];
    # ifndef HAVE_RB_IO_WAIT
        struct timeval *to = NULL, tv;
    # else
        VALUE timeout = Qnil;
    # endif

        GetOpenFile(io, fptr);
        if (optp) {
            if (optp->vtime) {
    # ifndef HAVE_RB_IO_WAIT
                to = &tv;
    # else
                struct timeval tv;
    # endif
                tv.tv_sec = optp->vtime / 10;
                tv.tv_usec = (optp->vtime % 10) * 100000;
    # ifdef HAVE_RB_IO_WAIT
                timeout = rb_fiber_scheduler_make_timeout(&tv);
    # endif
            }
            switch (optp->vmin) {
              case 1: /* default */
                break;
              case 0: /* return nil when timed out */
                if (optp->vtime) break;
                /* fallthru */
              default:
                rb_warning("min option larger than 1 ignored");
            }
            if (optp->intr) {
    # ifndef HAVE_RB_IO_WAIT
                int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
                if (w < 0) rb_eof_error();
                if (!(w & RB_WAITFD_IN)) return Qnil;
    # else
                VALUE result = rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), timeout);
                if (!RTEST(result)) return Qnil;
    # endif
            }
            else if (optp->vtime) {
                rb_warning("Non-zero vtime option ignored if intr flag is unset");
            }
        }
        len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0);
        switch (len) {
          case 0:
            return Qnil;
          case 2:
            buf[0] = (char)wbuf[0];
            c = wbuf[1];
            len = 1;
            do {
                buf[len++] = (unsigned char)c;
            } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf));
            return rb_str_new(buf, len);
          default:
            c = wbuf[0];
            len = rb_uv_to_utf8(buf, c);
            str = rb_utf8_str_new(buf, len);
            return rb_str_conv_enc(str, NULL, rb_default_external_encoding());
        }
    #endif
    }

getpass(prompt=nil) → string click to toggle source

Reads and returns a line without echo back. Prints `prompt` unless it is `nil`.

The newline character that terminates the read line is removed from the returned string, see `String#chomp!`.

You must require ‘io/console’ to use this method.

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

        rb_check_arity(argc, 0, 1);
        wio = rb_io_get_write_io(io);
        if (wio == io && io == rb_stdin) wio = rb_stderr;
        prompt(argc, argv, wio);
        str = rb_ensure(getpass_call, io, puts_call, wio);
        return str_chomp(str);
    }

gets(sep = $/, **getline_opts) → string or nil click to toggle source
gets(limit, **getline_opts) → string or nil
gets(sep, limit, **getline_opts) → string or nil

Reads and returns data from the stream; assigns the return value to `$_`.

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

    f = File.open('t.txt')
    f.gets # => "This is line one.\n"
    $_     # => "This is line one.\n"
    f.gets # => "This is the second line.\n"
    f.gets # => "This is the third line.\n"
    f.gets # => nil

With string argument `sep` given, but not argument `limit`, returns the next line as determined by line separator `sep`, or `nil` if none:

    f = File.open('t.txt')
    f.gets(' is') # => "This is"
    f.gets(' is') # => " line one.\nThis is"
    f.gets(' is') # => " the second line.\nThis is"
    f.gets(' is') # => " the third line.\n"
    f.gets(' is') # => nil

Note two special values for `sep`:

- `nil`: The entire stream is read and returned.

- `''` (empty string): The next “paragraph” is read and returned, the paragraph separator being two successive line separators.

With integer argument `limit` given, returns up to `limit+1` bytes:

    # Text with 1-byte characters.
    File.open('t.txt') {|f| f.gets(1) } # => "T"
    File.open('t.txt') {|f| f.gets(2) } # => "Th"
    File.open('t.txt') {|f| f.gets(3) } # => "Thi"
    File.open('t.txt') {|f| f.gets(4) } # => "This"
    # No more than one line.
    File.open('t.txt') {|f| f.gets(17) } # => "This is line one."
    File.open('t.txt') {|f| f.gets(18) } # => "This is line one.\n"
    File.open('t.txt') {|f| f.gets(19) } # => "This is line one.\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

With arguments `sep` and `limit`, combines the two behaviors above:

- Returns the next line as determined by line separator `sep`, or `nil` if none.

- But returns no more than `limit+1` bytes.

For all forms above, trailing optional keyword arguments may be given; see Getline Options:

    f = File.open('t.txt')
    # Chomp the lines.
    f.gets(chomp: true) # => "This is line one."
    f.gets(chomp: true) # => "This is the second line."
    f.gets(chomp: true) # => "This is the third line."
    f.gets(chomp: true) # => nil

    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;
    }

goto(p1, p2) click to toggle source

    static VALUE
    console_goto(VALUE io, VALUE y, VALUE x)
    {
        rb_io_t *fptr;
        int fd;
        COORD pos;

        GetOpenFile(io, fptr);
        fd = GetWriteFD(fptr);
        pos.X = NUM2UINT(x);
        pos.Y = NUM2UINT(y);
        if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) {
            rb_syserr_fail(LAST_ERROR, 0);
        }
        return io;
    }

goto_column(p1) click to toggle source

    static VALUE
    console_goto_column(VALUE io, VALUE val)
    {
        rb_io_t *fptr;
        HANDLE h;
        rb_console_size_t ws;
        COORD *pos = &ws.dwCursorPosition;

        GetOpenFile(io, fptr);
        h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
        if (!GetConsoleScreenBufferInfo(h, &ws)) {
            rb_syserr_fail(LAST_ERROR, 0);
        }
        pos->X = NUM2INT(val);
        if (!SetConsoleCursorPosition(h, *pos)) {
            rb_syserr_fail(LAST_ERROR, 0);
        }
        return io;
    }

iflush click to toggle source

Flushes input buffer in kernel.

You must require ‘io/console’ to use this method.

    static VALUE
    console_iflush(VALUE io)
    {
        rb_io_t *fptr;
        int fd;

        GetOpenFile(io, fptr);
        fd = GetReadFD(fptr);
    #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
        if (tcflush(fd, TCIFLUSH)) sys_fail_fptr(fptr);
    #endif
        (void)fd;
        return io;
    }

inspect → string click to toggle source

Returns a string representation of `self`:

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

    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_encoding → encoding click to toggle source

Returns the `Encoding` of the internal string if conversion is specified. Otherwise returns `nil`.

    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, arg) → integer click to toggle source

Provides a mechanism for issuing low-level commands to control or query I/O devices. Arguments and results are platform dependent. If arg is a number, its value is passed directly. If it is a string, it is interpreted as a binary sequence of bytes. On Unix platforms, see `ioctl(2)` for details. Not implemented on all platforms.

    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);
    }

ioflush click to toggle source

Flushes input and output buffers in kernel.

You must require ‘io/console’ to use this method.

    static VALUE
    console_ioflush(VALUE io)
    {
        rb_io_t *fptr;
    #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
        int fd1, fd2;
    #endif

        GetOpenFile(io, fptr);
    #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
        fd1 = GetReadFD(fptr);
        fd2 = GetWriteFD(fptr);
        if (fd2 != -1 && fd1 != fd2) {
            if (tcflush(fd1, TCIFLUSH)) sys_fail_fptr(fptr);
            if (tcflush(fd2, TCOFLUSH)) sys_fail_fptr(fptr);
        }
        else {
            if (tcflush(fd1, TCIOFLUSH)) sys_fail_fptr(fptr);
        }
    #endif
        return io;
    }

isatty → true or false click to toggle source

Returns `true` if ios is associated with a terminal device (tty), `false` otherwise.

    File.new("testfile").isatty   #=> false
    File.new("/dev/tty").isatty   #=> true

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

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

Also aliased as: tty?
lineno → integer click to toggle source

Returns the current line number in ios. The stream must be opened for reading. `lineno` counts the number of times `gets` is called rather than the number of newlines encountered. The two values will differ if `gets` is called with a separator other than newline.

Methods that use `$/` like `each`, lines and `readline` will also increment `lineno`.

See also the `$.` variable.

    f = File.new("testfile")
    f.lineno   #=> 0
    f.gets     #=> "This is line one\n"
    f.lineno   #=> 1
    f.gets     #=> "This is line two\n"
    f.lineno   #=> 2

    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 click to toggle source

Manually sets the current line number to the given value. `$.` is updated only on the next read.

    f = File.new("testfile")
    f.gets                     #=> "This is line one\n"
    $.                         #=> 1
    f.lineno = 1000
    f.lineno                   #=> 1000
    $.                         #=> 1         # lineno of last read
    f.gets                     #=> "This is line two\n"
    $.                         #=> 1001      # lineno of last read

    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;
    }

noecho {|io| } click to toggle source

Yields `self` with disabling echo back.

    STDIN.noecho(&:gets)

will read and return a line without echo back.

You must require ‘io/console’ to use this method.

    static VALUE
    console_noecho(VALUE io)
    {
        return ttymode(io, rb_yield, io, set_noecho, NULL);
    }

nonblock {|io| } → io click to toggle source
nonblock(boolean) {|io| } → io

Yields `self` in non-blocking mode.

When `false` is given as an argument, `self` is yielded in blocking mode. The original mode is restored after the block is executed.

    static VALUE
    rb_io_nonblock_block(int argc, VALUE *argv, VALUE io)
    {
        int nb = 1;
        rb_io_t *fptr;
        int f, restore[2];

        GetOpenFile(io, fptr);
        if (argc > 0) {
            VALUE v;
            rb_scan_args(argc, argv, "01", &v);
            nb = RTEST(v);
        }
        f = io_nonblock_mode(fptr->fd);
        restore[0] = fptr->fd;
        restore[1] = f;
        if (!io_nonblock_set(fptr->fd, f, nb))
            return rb_yield(io);
        return rb_ensure(rb_yield, io, io_nonblock_restore, (VALUE)restore);
    }

nonblock = boolean → boolean click to toggle source

Enables non-blocking mode on a stream when set to `true`, and blocking mode when set to `false`.

    static VALUE
    rb_io_nonblock_set(VALUE io, VALUE nb)
    {
        rb_io_t *fptr;
        GetOpenFile(io, fptr);
        if (RTEST(nb))
            rb_io_set_nonblock(fptr);
        else
            io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb));
        return io;
    }

nonblock? → boolean click to toggle source

Returns `true` if an `IO` object is in non-blocking mode.

    static VALUE
    rb_io_nonblock_p(VALUE io)
    {
        rb_io_t *fptr;
        GetOpenFile(io, fptr);
        if (io_nonblock_mode(fptr->fd) & O_NONBLOCK)
            return Qtrue;
        return Qfalse;
    }

nread → int click to toggle source

Returns number of bytes that can be read without blocking. Returns zero if no information available.

    static VALUE
    io_nread(VALUE io)
    {
        rb_io_t *fptr;
        int len;
        ioctl_arg n;

        GetOpenFile(io, fptr);
        rb_io_check_readable(fptr);
        len = rb_io_read_pending(fptr);
        if (len > 0) return INT2FIX(len);
        if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
        if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
        if (n > 0) return ioctl_arg2num(n);
        return INT2FIX(0);
    }

oflush click to toggle source

Flushes output buffer in kernel.

You must require ‘io/console’ to use this method.

    static VALUE
    console_oflush(VALUE io)
    {
        rb_io_t *fptr;
        int fd;

        GetOpenFile(io, fptr);
        fd = GetWriteFD(fptr);
    #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
        if (tcflush(fd, TCOFLUSH)) sys_fail_fptr(fptr);
    #endif
        (void)fd;
        return io;
    }

pathconf(p1) click to toggle source

Returns pathname configuration variable using fpathconf().

name should be a constant under `Etc` which begins with `PC_`.

The return value is an integer or nil. nil means indefinite limit. (fpathconf() returns -1 but errno is not set.)

    require 'etc'
    IO.pipe {|r, w|
      p w.pathconf(Etc::PC_PIPE_BUF) #=> 4096
    }

    static VALUE
    io_pathconf(VALUE io, VALUE arg)
    {
        int name;
        long ret;
        rb_io_t *fptr;

        name = NUM2INT(arg);

        GetOpenFile(io, fptr);

        errno = 0;
        ret = fpathconf(fptr->fd, name);
        if (ret == -1) {
            if (errno == 0) /* no limit */
                return Qnil;
            rb_sys_fail("fpathconf");
        }
        return LONG2NUM(ret);
    }

pid → integer or nil click to toggle source

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

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

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

pos()

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

    f = File.new('t.txt')
    f.tell     # => 0
    f.readline # => "This is line one.\n"
    f.tell     # => 19

Related: `IO#pos=`, `IO#seek`.

`IO#pos` is an alias for `IO#tell`.

Alias for: tell
pos = new_position → new_position click to toggle source

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

Related: `IO#seek`, `IO#tell`.

    static VALUE
    rb_io_set_pos(VALUE io, VALUE offset)
    {
        rb_io_t *fptr;
        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[, outbuf]) → string click to toggle source

Reads maxlen bytes from ios using the pread system call and returns them as a string without modifying the underlying descriptor offset. This is advantageous compared to combining `IO#seek` and `IO#read` in that it is atomic, allowing multiple threads/process to share the same `IO` object for reading the file at various locations. This bypasses any userspace buffering of the `IO` layer. If the optional outbuf argument is present, it must reference a `String`, which will receive the data. Raises `SystemCallError` on error, `EOFError` at end of file and `NotImplementedError` if platform does not implement the system call.

    File.write("testfile", "This is line one\nThis is line two\n")
    File.open("testfile") do |f|
      p f.read           # => "This is line one\nThis is line two\n"
      p f.pread(12, 0)   # => "This is line"
      p f.pread(9, 8)    # => "line one\n"
    end

    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.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;
    }

pressed?(p1) click to toggle source

    static VALUE
    console_key_pressed_p(VALUE io, VALUE k)
    {
        int vk = -1;

        if (FIXNUM_P(k)) {
            vk = NUM2UINT(k);
        }
        else {
            const struct vktable *t;
            const char *kn;
            if (SYMBOL_P(k)) {
                k = rb_sym2str(k);
                kn = RSTRING_PTR(k);
            }
            else {
                kn = StringValuePtr(k);
            }
            t = console_win32_vk(kn, RSTRING_LEN(k));
            if (!t || (vk = (short)t->vk) == -1) {
                rb_raise(rb_eArgError, "unknown virtual key code: % "PRIsVALUE, k);
            }
        }
        return GetKeyState(vk) & 0x80 ? Qtrue : Qfalse;
    }

print → nil click to toggle source
print(obj, ...) → nil

Writes the given object(s) to ios. Returns `nil`.

The stream must be opened for writing. Each given object that isn’t a string will be converted by calling its `to_s` method. When called without arguments, prints the contents of `$_`.

If the output field separator (`$,`) is not `nil`, it is inserted between objects. If the output record separator (`$\`) is not `nil`, it is appended to the output.

    $stdout.print("This is ", 100, " percent.\n")

produces:

    This is 100 percent.

    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 [, obj, ...]) → nil click to toggle source

Formats and writes to ios, converting parameters under control of the format string. See `Kernel#sprintf` for details.

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

putc(obj) → obj click to toggle source

If obj is `Numeric`, write the character whose code is the least-significant byte of obj. If obj is `String`, write the first character of obj to ios. Otherwise, raise `TypeError`.

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

produces:

    AA

    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(obj, ...) → nil click to toggle source

Writes the given object(s) to ios. Writes a newline after any that do not already end with a newline sequence. Returns `nil`.

The stream must be opened for writing. If called with an array argument, writes each element on a new line. Each given object that isn’t a string or array will be converted by calling its `to_s` method. If called without arguments, outputs a single newline.

    $stdout.puts("this", "is", ["a", "test"])

produces:

    this
    is
    a
    test

Note that `puts` always uses newlines and is not affected by the output record separator (`$\`).

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

        /* if no argument given, print newline. */
        if (argc == 0) {
            rb_io_write(out, rb_default_rs);
            return Qnil;
        }
        for (i=0; i<argc; i++) {
            if (RB_TYPE_P(argv[i], T_STRING)) {
                line = argv[i];
                goto string;
            }
            if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
                continue;
            }
            line = rb_obj_as_string(argv[i]);
          string:
            n = 0;
            args[n++] = line;
            if (RSTRING_LEN(line) == 0 ||
                !rb_str_end_with_asciichar(line, '\n')) {
                args[n++] = rb_default_rs;
            }
            rb_io_writev(out, n, args);
        }

        return Qnil;
    }

pwrite(string, offset) → integer click to toggle source

Writes the given string to ios at offset using pwrite() system call. This is advantageous to combining `IO#seek` and `IO#write` in that it is atomic, allowing multiple threads/process to share the same `IO` object for reading the file at various locations. This bypasses any userspace buffering of the `IO` layer. Returns the number of bytes written. Raises `SystemCallError` on error and `NotImplementedError` if platform does not implement the system call.

    File.open("out", "w") do |f|
      f.pwrite("ABCDEF", 3)   #=> 6
    end

    File.read("out")          #=> "\u0000\u0000\u0000ABCDEF"

    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.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_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
        if (n < 0) rb_sys_fail_path(fptr->pathv);
        rb_str_tmp_frozen_release(str, tmp);

        return SSIZET2NUM(n);
    }

raw(min: nil, time: nil, intr: nil) {|io| } click to toggle source

Yields `self` within raw mode, and returns the result of the block.

    STDIN.raw(&:gets)

will read and return a line without echo back and line editing.

The parameter `min` specifies the minimum number of bytes that should be received when a read operation is performed. (default: 1)

The parameter `time` specifies the timeout in seconds with a precision of 1/10 of a second. (default: 0)

If the parameter `intr` is `true`, enables break, interrupt, quit, and suspend special characters.

Refer to the manual page of termios for further details.

You must require ‘io/console’ to use this method.

    static VALUE
    console_raw(int argc, VALUE *argv, VALUE io)
    {
        rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
        return ttymode(io, rb_yield, io, set_rawmode, optp);
    }

raw!(min: nil, time: nil, intr: nil) → io click to toggle source

Enables raw mode, and returns `io`.

If the terminal mode needs to be back, use `io.raw { ... }`.

See `IO#raw` for details on the parameters.

You must require ‘io/console’ to use this method.

    static VALUE
    console_set_raw(int argc, VALUE *argv, VALUE io)
    {
        conmode t;
        rb_io_t *fptr;
        int fd;
        rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);

        GetOpenFile(io, fptr);
        fd = GetReadFD(fptr);
        if (!getattr(fd, &t)) sys_fail_fptr(fptr);
        set_rawmode(&t, optp);
        if (!setattr(fd, &t)) sys_fail_fptr(fptr);
        return io;
    }

read(maxlen = nil) → string or nil click to toggle source
read(maxlen = nil, out_string) → out_string or nil

Reads bytes from the stream (in binary mode):

- If `maxlen` is `nil`, reads all bytes.

- Otherwise reads `maxlen` bytes, if available.

- Otherwise reads all bytes.

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
    # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
    f.rewind
    f.read(40)      # => "This is line one.\r\nThis is the second li"
    f.read(40)      # => "ne.\r\nThis is the third line.\r\n"
    f.read(40)      # => nil

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) # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
    s              # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
    f.rewind
    s = 'bar'
    f.read(40, s)  # => "This is line one.\r\nThis is the second li"
    s              # => "This is line one.\r\nThis is the second li"
    s = 'baz'
    f.read(40, s)  # => "ne.\r\nThis is the third line.\r\n"
    s              # => "ne.\r\nThis is the third line.\r\n"
    s = 'bat'
    f.read(40, s)  # => nil
    s              # => ""

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

    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;
    }

read_nonblock(maxlen [, options]) → string click to toggle source
read_nonblock(maxlen, outbuf [, options]) → outbuf

Reads at most maxlen bytes from ios using the read(2) system call after O_NONBLOCK is set for the underlying file descriptor.

If the optional outbuf argument is present, it must reference a `String`, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning.

`read_nonblock` just calls the read(2) system call. It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc. The caller should care such errors.

If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN, it is extended by `IO::WaitReadable`. So `IO::WaitReadable` can be used to rescue the exceptions for retrying read_nonblock.

`read_nonblock` causes `EOFError` on EOF.

On some platforms, such as Windows, non-blocking mode is not supported on `IO` objects other than sockets. In such cases, Errno::EBADF will be raised.

If the read byte buffer is not empty, `read_nonblock` reads from the buffer like readpartial. In this case, the read(2) system call is not called.

When `read_nonblock` raises an exception kind of `IO::WaitReadable`, `read_nonblock` should not be called until io is readable for avoiding busy loop. This can be done as follows.

    # emulates blocking read (readpartial).
    begin
      result = io.read_nonblock(maxlen)
    rescue IO::WaitReadable
      IO.select([io])
      retry
    end

Although `IO#read_nonblock` doesn’t raise `IO::WaitWritable`. `OpenSSL::Buffering#read_nonblock` can raise `IO::WaitWritable`. If `IO` and SSL should be used polymorphically, `IO::WaitWritable` should be rescued too. See the document of `OpenSSL::Buffering#read_nonblock` for sample code.

Note that this method is identical to readpartial except the non-blocking flag is set.

By specifying a keyword argument exception to `false`, you can indicate that `read_nonblock` should not raise an `IO::WaitReadable` exception, but return the symbol `:wait_readable` instead. At EOF, it will return nil instead of raising `EOFError`.

    # File io.rb, line 62
    def read_nonblock(len, buf = nil, exception: true)
      Primitive.io_read_nonblock(len, buf, exception)
    end

readbyte → integer click to toggle source

Reads a byte as with `IO#getbyte`, but raises an `EOFError` on end of file.

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

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

readchar → string click to toggle source

Reads a one-character string from ios. Raises an `EOFError` on end of file.

    f = File.new("testfile")
    f.readchar   #=> "h"
    f.readchar   #=> "e"

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

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

readline(sep=$/ [, getline_args]) → string click to toggle source
readline(limit [, getline_args]) → string
readline(sep, limit [, getline_args]) → string

Reads a line as with `IO#gets`, but raises an `EOFError` on end of file.

    static VALUE
    rb_io_readline(int argc, VALUE *argv, VALUE io)
    {
        VALUE line = rb_io_gets_m(argc, argv, io);

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

readlines(sep=$/ [, getline_args]) → array click to toggle source
readlines(limit [, getline_args]) → array
readlines(sep, limit [, getline_args]) → array

Reads all of the lines in ios, and returns them in an array. Lines are separated by the optional sep. If sep is `nil`, the rest of the stream is returned as a single record. If the first argument is an integer, or an optional second argument is given, the returning string would not be longer than the given value in bytes. The stream must be opened for reading or an `IOError` will be raised.

    f = File.new("testfile")
    f.readlines[0]   #=> "This is line one\n"

    f = File.new("testfile", chomp: true)
    f.readlines[0]   #=> "This is line one"

See `IO.readlines` for details about getline_args.

    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 click to toggle source
readpartial(maxlen, out_string) → out_string

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(30) # => "This is line one.\nThis is the"
    f.readpartial(30) # => " second line.\nThis is the thi"
    f.readpartial(30) # => "rd line.\n"
    f.eof             # => true
    f.readpartial(30) # Raises EOFError.

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

    f = File.new('t.txt')
    s = 'foo'
    f.readpartial(30, s) # => "This is line one.\nThis is the"
    s = 'bar'
    f.readpartial(0, s)  # => ""

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

    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;
    }

ready? → true or false click to toggle source

Returns `true` if input available without blocking, or `false`.

    static VALUE
    io_ready_p(VALUE io)
    {
        rb_io_t *fptr;
    #ifndef HAVE_RB_IO_WAIT
        struct timeval tv = {0, 0};
    #endif

        GetOpenFile(io, fptr);
        rb_io_check_readable(fptr);
        if (rb_io_read_pending(fptr)) return Qtrue;

    #ifndef HAVE_RB_IO_WAIT
        if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
            return Qtrue;
    #else
        if (RTEST(io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0))))
            return Qtrue;
    #endif
        return Qfalse;
    }

reopen(other_IO) → ios click to toggle source
reopen(path, mode [, opt]) → ios

Reassociates ios with the I/O stream given in other_IO or to a new stream opened on path. This may dynamically change the actual class of this stream. The `mode` and `opt` parameters accept the same values as `IO.open`.

    f1 = File.new("testfile")
    f2 = File.new("testfile")
    f2.readlines[0]   #=> "This is line one\n"
    f2.reopen(f1)     #=> #<File:testfile>
    f2.readlines[0]   #=> "This is line one\n"

    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;
            convconfig_t convconfig;

            rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
            if (IS_PREP_STDIO(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;
    }

rewind → 0 click to toggle source

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.readline # => "This is line one.\n"
    f.tell     # => 19
    f.lineno   # => 1
    f.rewind   # => 0
    f.tell     # => 0
    f.lineno   # => 0

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

    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);
    }

scroll_backward(p1) click to toggle source

    static VALUE
    console_scroll_backward(VALUE io, VALUE val)
    {
        return console_scroll(io, -NUM2INT(val));
    }

scroll_forward(p1) click to toggle source

    static VALUE
    console_scroll_forward(VALUE io, VALUE val)
    {
        return console_scroll(io, +NUM2INT(val));
    }

seek(offset, whence = IO::SEEK_SET) → 0 click to toggle source

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

- `: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            # => 70
      f.seek(-20, :END) # => 0
      f.tell            # => 50
      f.seek(-40, :END) # => 0
      f.tell            # => 30

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

Related: `IO#pos=`, `IO#tell`.

    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) → io click to toggle source
set_encoding("ext_enc:int_enc") → io
set_encoding(ext_enc, int_enc) → io
set_encoding("ext_enc:int_enc", opt) → io
set_encoding(ext_enc, int_enc, opt) → io

If single argument is specified, read string from io is tagged with the encoding specified. If encoding is a colon separated two encoding names “A:B”, the read string is converted from encoding A (external encoding) to encoding B (internal encoding), then tagged with B. If two arguments are specified, those must be encoding objects or encoding names, and the first one is the external encoding, and the second one is the internal encoding. If the external encoding and the internal encoding is specified, optional hash argument specify the conversion option.

    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_bom → encoding or nil click to toggle source

Checks if `ios` starts with a BOM, and then consumes it and sets the external encoding. Returns the result encoding if found, or nil. If `ios` is not binmode or its encoding has been set already, an exception will be raised.

    File.write("bom.txt", "\u{FEFF}abc")
    ios = File.open("bom.txt", "rb")
    ios.set_encoding_by_bom    #=>  #<Encoding:UTF-8>

    File.write("nobom.txt", "abc")
    ios = File.open("nobom.txt", "rb")
    ios.set_encoding_by_bom    #=>  nil

    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);
    }

stat → stat click to toggle source

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

    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);
    }

sync → true or false click to toggle source

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

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

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

sync = boolean → boolean click to toggle source

Sets the sync mode for the stream to the given value; returns the given value.

Values for the sync mode:

- `true`: All output is immediately flushed to the underlying operating system and is not buffered internally.

- `false`: Output may be buffered internally.

Example;

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

Related: `IO#fsync`.

    static VALUE
    rb_io_set_sync(VALUE io, VALUE sync)
    {
        rb_io_t *fptr;

        io = GetWriteIO(io);
        GetOpenFile(io, fptr);
        if (RTEST(sync)) {
            fptr->mode |= FMODE_SYNC;
        }
        else {
            fptr->mode &= ~FMODE_SYNC;
        }
        return sync;
    }

sysread(maxlen[, outbuf]) → string click to toggle source

Reads maxlen bytes from ios using a low-level read and returns them as a string. Do not mix with other methods that read from ios or you may get unpredictable results.

If the optional outbuf argument is present, it must reference a `String`, which will receive the data. The outbuf will contain only the received data after the method call even if it is not empty at the beginning.

Raises `SystemCallError` on error and `EOFError` at end of file.

    f = File.new("testfile")
    f.sysread(16)   #=> "This is line one"

    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.buf = RSTRING_PTR(str);
        iis.capa = ilen;
        n = read_internal_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 click to toggle source

Seeks to a given offset in the stream according to the value of whence (see `IO#seek` for values of whence). Returns the new offset into the file.

    f = File.new("testfile")
    f.sysseek(-13, IO::SEEK_END)   #=> 53
    f.sysread(10)                  #=> "And so on."

    static VALUE
    rb_io_sysseek(int argc, VALUE *argv, VALUE io)
    {
        VALUE offset, ptrname;
        int whence = SEEK_SET;
        rb_io_t *fptr;
        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(string) → integer click to toggle source

Writes the given string to ios using a low-level write. Returns the number of bytes written. Do not mix with other methods that write to ios or you may get unpredictable results. Raises `SystemCallError` on error.

    f = File.new("out", "w")
    f.syswrite("ABCDEF")   #=> 6

    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_write_internal(fptr, ptr, len);
        if (n < 0) rb_sys_fail_path(fptr->pathv);
        rb_str_tmp_frozen_release(str, tmp);

        return LONG2FIX(n);
    }

tell → integer click to toggle source

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

    f = File.new('t.txt')
    f.tell     # => 0
    f.readline # => "This is line one.\n"
    f.tell     # => 19

Related: `IO#pos=`, `IO#seek`.

`IO#pos` is an alias for `IO#tell`.

    static VALUE
    rb_io_tell(VALUE io)
    {
        rb_io_t *fptr;
        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);
    }

Also aliased as: pos
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

`IO#to_i` is an alias for `IO#fileno`.

Alias for: fileno
to_io → self click to toggle source

Returns `self`.

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

tty? → true or false

Returns `true` if ios is associated with a terminal device (tty), `false` otherwise.

    File.new("testfile").isatty   #=> false
    File.new("/dev/tty").isatty   #=> true

Alias for: isatty
ungetbyte(string) → nil click to toggle source
ungetbyte(integer) → nil

Pushes back bytes (passed as a parameter) onto ios, such that a subsequent buffered read will return it. It is only guaranteed to support a single byte, and only if ungetbyte or ungetc has not already been called on ios since the previous read of at least a single byte from ios. However, it can support additional bytes if there is space in the internal buffer to allow for it.

    f = File.new("testfile")   #=> #<File:testfile>
    b = f.getbyte              #=> 0x38
    f.ungetbyte(b)             #=> nil
    f.getbyte                  #=> 0x38

If given an integer, only uses the lower 8 bits of the integer as the byte to push.

    f = File.new("testfile")   #=> #<File:testfile>
    f.ungetbyte(0x102)         #=> nil
    f.getbyte                  #=> 0x2

Calling this method prepends to the existing buffer, even if the method has already been called previously:

    f = File.new("testfile")   #=> #<File:testfile>
    f.ungetbyte("ab")          #=> nil
    f.ungetbyte("cd")          #=> nil
    f.read(5)                  #=> "cdab8"

Has no effect with unbuffered reads (such as `IO#sysread`).

    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:
            SafeStringValue(b);
        }
        io_ungetbyte(b, fptr);
        return Qnil;
    }

ungetc(integer) → nil click to toggle source
ungetc(string) → nil

Pushes back characters (passed as a parameter) onto ios, such that a subsequent buffered read will return it. It is only guaranteed to support a single byte, and only if ungetbyte or ungetc has not already been called on ios since the previous read of at least a single byte from ios. However, it can support additional bytes if there is space in the internal buffer to allow for it.

    f = File.new("testfile")   #=> #<File:testfile>
    c = f.getc                 #=> "8"
    f.ungetc(c)                #=> nil
    f.getc                     #=> "8"

If given an integer, the integer must represent a valid codepoint in the external encoding of ios.

Calling this method prepends to the existing buffer, even if the method has already been called previously:

    f = File.new("testfile")   #=> #<File:testfile>
    f.ungetc("ab")             #=> nil
    f.ungetc("cd")             #=> nil
    f.read(5)                  #=> "cdab8"

Has no effect with unbuffered reads (such as `IO#sysread`).

    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 {
            SafeStringValue(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) → event mask or false. click to toggle source
wait(timeout = nil, mode = :read) → event mask or false.

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

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

Returns `true` immediately when buffered data is available.

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

    static VALUE
    io_wait(int argc, VALUE *argv, VALUE io)
    {
    #ifndef HAVE_RB_IO_WAIT
        rb_io_t *fptr;
        struct timeval timerec;
        struct timeval *tv = NULL;
        int event = 0;
        int i;

        GetOpenFile(io, fptr);
        for (i = 0; i < argc; ++i) {
            if (SYMBOL_P(argv[i])) {
                event |= wait_mode_sym(argv[i]);
            }
            else {
                *(tv = &timerec) = rb_time_interval(argv[i]);
            }
        }
        /* rb_time_interval() and might_mode() might convert the argument */
        rb_io_check_closed(fptr);
        if (!event) event = RB_WAITFD_IN;
        if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
            return Qtrue;
        if (wait_for_single_fd(fptr, event, tv))
            return io;
        return Qnil;
    #else
        VALUE timeout = Qundef;
        rb_io_event_t events = 0;

        if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
            for (int i = 0; i < argc; i += 1) {
                if (RB_SYMBOL_P(argv[i])) {
                    events |= wait_mode_sym(argv[i]);
                }
                else if (timeout == Qundef) {
                    rb_time_interval(timeout = argv[i]);
                }
                else {
                    rb_raise(rb_eArgError, "timeout given more than once");
                }
            }
            if (timeout == Qundef) timeout = Qnil;
        }
        else /* argc == 2 */ {
            events = RB_NUM2UINT(argv[0]);
            timeout = argv[1];
        }

        if (events == 0) {
            events = RUBY_IO_READABLE;
        }

        if (events & RUBY_IO_READABLE) {
            rb_io_t *fptr = NULL;
            RB_IO_POINTER(io, fptr);

            if (rb_io_read_pending(fptr)) {
                return Qtrue;
            }
        }

        return io_wait_event(io, events, timeout);
    #endif
    }

wait_priority → true or false click to toggle source
wait_priority(timeout) → true or false

Waits until `IO` is priority and returns `true` or `false` when times out.

    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);
    }

wait_readable → true or false click to toggle source
wait_readable(timeout) → true or false

Waits until `IO` is readable and returns `true`, or `false` when times out. Returns `true` immediately when buffered data is available.

    static VALUE
    io_wait_readable(int argc, VALUE *argv, VALUE io)
    {
        rb_io_t *fptr;
    #ifndef HAVE_RB_IO_WAIT
        struct timeval timerec;
        struct timeval *tv;
    #endif

        GetOpenFile(io, fptr);
        rb_io_check_readable(fptr);

    #ifndef HAVE_RB_IO_WAIT
        tv = get_timeout(argc, argv, &timerec);
    #endif
        if (rb_io_read_pending(fptr)) return Qtrue;

    #ifndef HAVE_RB_IO_WAIT
        if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
            return io;
        }
        return Qnil;
    #else
        rb_check_arity(argc, 0, 1);
        VALUE timeout = (argc == 1 ? argv[0] : Qnil);

        return io_wait_event(io, RUBY_IO_READABLE, timeout);
    #endif
    }

wait_writable → true or false click to toggle source
wait_writable(timeout) → true or false

Waits until `IO` is writable and returns `true` or `false` when times out.

    static VALUE
    io_wait_writable(int argc, VALUE *argv, VALUE io)
    {
        rb_io_t *fptr;
    #ifndef HAVE_RB_IO_WAIT
        struct timeval timerec;
        struct timeval *tv;
    #endif

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

    #ifndef HAVE_RB_IO_WAIT
        tv = get_timeout(argc, argv, &timerec);
        if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
            return io;
        }
        return Qnil;
    #else
        rb_check_arity(argc, 0, 1);
        VALUE timeout = (argc == 1 ? argv[0] : Qnil);

        return io_wait_event(io, RUBY_IO_WRITABLE, timeout);
    #endif
    }

winsize → [rows, columns] click to toggle source

Returns console size.

You must require ‘io/console’ to use this method.

    static VALUE
    console_winsize(VALUE io)
    {
        rb_io_t *fptr;
        int fd;
        rb_console_size_t ws;

        GetOpenFile(io, fptr);
        fd = GetWriteFD(fptr);
        if (!getwinsize(fd, &ws)) sys_fail_fptr(fptr);
        return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
    }

winsize = [rows, columns] click to toggle source

Tries to set console size. The effect depends on the platform and the running environment.

You must require ‘io/console’ to use this method.

    static VALUE
    console_set_winsize(VALUE io, VALUE size)
    {
        rb_io_t *fptr;
        rb_console_size_t ws;
    #if defined _WIN32
        HANDLE wh;
        int newrow, newcol;
        BOOL ret;
    #endif
        VALUE row, col, xpixel, ypixel;
        const VALUE *sz;
        int fd;
        long sizelen;

        GetOpenFile(io, fptr);
        size = rb_Array(size);
        if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) {
            rb_raise(rb_eArgError,
                     "wrong number of arguments (given %ld, expected 2 or 4)",
                     sizelen);
        }
        sz = RARRAY_CONST_PTR(size);
        row = sz[0], col = sz[1], xpixel = ypixel = Qnil;
        if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
        fd = GetWriteFD(fptr);
    #if defined TIOCSWINSZ
        ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
    #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
        SET(row);
        SET(col);
        SET(xpixel);
        SET(ypixel);
    #undef SET
        if (!setwinsize(fd, &ws)) sys_fail_fptr(fptr);
    #elif defined _WIN32
        wh = (HANDLE)rb_w32_get_osfhandle(fd);
    #define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
        SET(row);
        SET(col);
    #undef SET
        if (!NIL_P(xpixel)) (void)NUM2UINT(xpixel);
        if (!NIL_P(ypixel)) (void)NUM2UINT(ypixel);
        if (!GetConsoleScreenBufferInfo(wh, &ws)) {
            rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
        }
        ws.dwSize.X = newcol;
        ret = SetConsoleScreenBufferSize(wh, ws.dwSize);
        ws.srWindow.Left = 0;
        ws.srWindow.Top = 0;
        ws.srWindow.Right = newcol-1;
        ws.srWindow.Bottom = newrow-1;
        if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
            rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
        }
        /* retry when shrinking buffer after shrunk window */
        if (!ret && !SetConsoleScreenBufferSize(wh, ws.dwSize)) {
            rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
        }
        /* remove scrollbar if possible */
        if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
            rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
        }
    #endif
        return io;
    }

write(*objects) → integer click to toggle source

Writes each of the given `objects` to `self`, which must be opened for writing (see 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

    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);
        }
    }

write_nonblock(string) → integer click to toggle source
write_nonblock(string [, options]) → integer

Writes the given string to ios using the write(2) system call after O_NONBLOCK is set for the underlying file descriptor.

It returns the number of bytes written.

`write_nonblock` just calls the write(2) system call. It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc. The result may also be smaller than string.length (partial write). The caller should care such errors and partial write.

If the exception is Errno::EWOULDBLOCK or Errno::EAGAIN, it is extended by `IO::WaitWritable`. So `IO::WaitWritable` can be used to rescue the exceptions for retrying write_nonblock.

    # Creates a pipe.
    r, w = IO.pipe

    # write_nonblock writes only 65536 bytes and return 65536.
    # (The pipe size is 65536 bytes on this environment.)
    s = "a" * 100000
    p w.write_nonblock(s)     #=> 65536

    # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
    p w.write_nonblock("b")   # Resource temporarily unavailable (Errno::EAGAIN)

If the write buffer is not empty, it is flushed at first.

When `write_nonblock` raises an exception kind of `IO::WaitWritable`, `write_nonblock` should not be called until io is writable for avoiding busy loop. This can be done as follows.

    begin
      result = io.write_nonblock(string)
    rescue IO::WaitWritable, Errno::EINTR
      IO.select(nil, [io])
      retry
    end

Note that this doesn’t guarantee to write all data in string. The length written is reported as result and it should be checked later.

On some platforms such as Windows, `write_nonblock` is not supported according to the kind of the `IO` object. In such cases, `write_nonblock` raises `Errno::EBADF`.

By specifying a keyword argument exception to `false`, you can indicate that `write_nonblock` should not raise an `IO::WaitWritable` exception, but return the symbol `:wait_writable` instead.

    # File io.rb, line 120
    def write_nonblock(buf, exception: true)
      Primitive.io_write_nonblock(buf, exception)
    end