class IO

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

ClassFile is the only class in the Ruby core that is a subclass of IO. Some classes in the Ruby standard library are also subclasses of IO; these includeTCPSocket andUDPSocket.

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

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

Important objects based on IO include:

An instance of IO may be created using:

Like aFile stream, an IO stream has:

And like other IO streams, it has:

Extensionio/console

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

Example Files

Many examples here use these variables:

# English text with newlines.text =<<~EOT  First line  Second line  Fourth line  Fifth lineEOT# Russian text.russian ="\u{442 435 441 442}"# => "тест"# Binary data.data ="\u9990\u9991\u9992\u9993\u9994"# Text file.File.write('t.txt',text)# File with Russian text.File.write('t.rus',russian)# File with binary data.f =File.new('t.dat','wb:UTF-16')f.write(data)f.close

Open Options

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

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

Basic IO

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

Position

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

These methods discardbuffers and theEncoding::Converter instances used for that IO.

The relevant methods:

Open and Closed Streams

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

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

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

The relevant methods:

End-of-Stream

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

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

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

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

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

Line IO

Class IO supports line-orientedinput andoutput

Line Input

Class IO supports line-oriented input forfiles andIO streams

File Line Input

You can read lines from a file using these methods:

For each of these methods:

Stream Line Input

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

For each of these methods:

Line Separator

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

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

Generally, the line to be read next is all data from the currentposition to the next line separator (but seeSpecial Line Separator Values):

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

You can use a different line separator by passing argumentsep:

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

Or by setting global variable$/:

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

Each of theline input methods accepts two special values for parametersep:

Line Limit

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

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

If there is no limit, the line is determined only bysep.

# Text with 1-byte characters.File.open('t.txt') {|f|f.gets(1) }# => "F"File.open('t.txt') {|f|f.gets(2) }# => "Fi"File.open('t.txt') {|f|f.gets(3) }# => "Fir"File.open('t.txt') {|f|f.gets(4) }# => "Firs"# No more than one line.File.open('t.txt') {|f|f.gets(10) }# => "First line"File.open('t.txt') {|f|f.gets(11) }# => "First line\n"File.open('t.txt') {|f|f.gets(12) }# => "First line\n"# Text with 2-byte characters, which will not be split.File.open('t.rus') {|f|f.gets(1).size }# => 1File.open('t.rus') {|f|f.gets(2).size }# => 1File.open('t.rus') {|f|f.gets(3).size }# => 2File.open('t.rus') {|f|f.gets(4).size }# => 2
Line Separator and Line Limit

With argumentssep andlimit given, combines the two behaviors:

Example:

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

A readable IO stream has a non-negative integerline number:

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

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

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

Reading lines from a stream usually changes its line number:

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

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

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

Output:

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

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

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

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

Line Output

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

Character IO

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

Byte IO

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

Codepoint IO

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

What’s Here

First, what’s elsewhere. Class IO:

Here, class IO provides methods that are useful for:

Creating

Reading

Writing

Positioning

Iterating

Settings

Querying

Buffering

Low-Level Access

Other

Constants

EWOULDBLOCKWaitReadable

same asIO::EAGAINWaitReadable

EWOULDBLOCKWaitWritable

same asIO::EAGAINWaitWritable

PRIORITY

Priority event mask forIO#wait.

READABLE

Readable event mask forIO#wait.

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

Writable event mask forIO#wait.

Public Class Methods

Source
static VALUErb_io_s_binread(int argc, VALUE *argv, VALUE io){    VALUE offset;    struct foreach_arg arg;    enum rb_io_mode fmode = FMODE_READABLE|FMODE_BINMODE;    enum {        oflags = O_RDONLY#ifdef O_BINARY                |O_BINARY#endif    };    struct rb_io_encoding convconfig = {NULL, NULL, 0, Qnil};    rb_scan_args(argc, argv, "12", NULL, NULL, &offset);    FilePathValue(argv[0]);    convconfig.enc = rb_ascii8bit_encoding();    arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);    if (NIL_P(arg.io)) return Qnil;    arg.argv = argv+1;    arg.argc = (argc > 1) ? 1 : 0;    if (!NIL_P(offset)) {        struct seek_arg sarg;        int state = 0;        sarg.io = arg.io;        sarg.offset = offset;        sarg.mode = SEEK_SET;        rb_protect(seek_before_access, (VALUE)&sarg, &state);        if (state) {            rb_io_close(arg.io);            rb_jump_tag(state);        }    }    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);}

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

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

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

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

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

Source
static VALUEconsole_dev(int argc, VALUE *argv, VALUE klass){    VALUE con = 0;    VALUE sym = 0;    rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS);    if (argc) {        Check_Type(sym = argv[0], T_SYMBOL);    }    // Force the class to be File.    if (klass == rb_cIO) klass = rb_cFile;    if (console_dev_get(klass, &con)) {        if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) {            console_dev_remove(klass);            con = 0;        }    }    if (sym) {        if (sym == ID2SYM(id_close) && argc == 1) {            if (con) {                rb_io_close(con);                console_dev_remove(klass);                con = 0;            }            return Qnil;        }    }    if (!con) {#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;#endif        int fd;        VALUE path = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));#ifdef CONSOLE_DEVICE_FOR_WRITING        fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0);        if (fd < 0) return Qnil;        out = rb_io_open_descriptor(klass, fd, FMODE_WRITABLE | FMODE_SYNC, path, Qnil, NULL);#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;        }        con = rb_io_open_descriptor(klass, fd, FMODE_READWRITE | FMODE_SYNC, path, Qnil, NULL);#ifdef CONSOLE_DEVICE_FOR_WRITING        rb_io_set_write_io(con, out);#endif        console_dev_set(klass, con);    }    if (sym) {        return rb_f_send(argc, argv, con);    }    return con;}

Returns anFile instance opened console.

Ifsym is given, it will be sent to the opened console withargs and the result will be returned instead of the consoleIO itself.

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

Source
static VALUErb_io_s_copy_stream(int argc, VALUE *argv, VALUE io){    VALUE src, dst, length, src_offset;    struct copy_stream_struct st;    MEMZERO(&st, struct copy_stream_struct, 1);    rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);    st.src = src;    st.dst = dst;    st.src_fptr = NULL;    st.dst_fptr = NULL;    if (NIL_P(length))        st.copy_length = (rb_off_t)-1;    else        st.copy_length = NUM2OFFT(length);    if (NIL_P(src_offset))        st.src_offset = (rb_off_t)-1;    else        st.src_offset = NUM2OFFT(src_offset);    rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);    return OFFT2NUM(st.total);}

Copies from the givensrc to the givendst, returning the number of bytes copied.

  • The givensrc must be one of the following:

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

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

  • The givendst must be one of the following:

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

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

The examples here use filet.txt as source:

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

If only argumentssrc anddst are given, the entire source stream is copied:

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

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

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

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

IO.copy_stream('t.txt','t.tmp',11,11)# => 11IO.read('t.tmp')# => "Second line"
Source
static VALUErb_io_s_for_fd(int argc, VALUE *argv, VALUE klass){    VALUE io = rb_obj_alloc(klass);    rb_io_initialize(argc, argv, io);    return io;}

Synonym forIO.new.

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

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

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

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

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

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

Output: the same as above.

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

With argumentsep given, parses lines as determined by that line separator (seeLine Separator):

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

Output:

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

Each paragraph:

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

Output:

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

With argumentlimit given, parses lines as determined by the default line separator and the given line-length limit (seeLine Separator andLine Limit):

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

Output:

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

With argumentssep andlimit given, combines the two behaviors (seeLine Separator and Line Limit).

Optional keyword argumentsopts specify:

Returns anEnumerator if no block is given.

Source
static VALUErb_io_initialize(int argc, VALUE *argv, VALUE io){    VALUE fnum, vmode;    VALUE opt;    rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);    return io_initialize(io, fnum, vmode, opt);}

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

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

Argumentfd must be a valid file descriptor (integer):

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

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

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

Optional argumentmode (defaults to ‘r’) must specify a valid mode; seeAccess Modes:

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

Optional keyword argumentsopts specify:

Examples:

IO.new(fd,internal_encoding:nil)# => #<IO:fd 3>IO.new(fd,autoclose:true)# => #<IO:fd 3>
Source
static VALUErb_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;}

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

With no block given, returns the IO object.

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

Source
static VALUErb_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;    enum rb_io_mode 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;}

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

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

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

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

If argumentint_enc is given, it must be anEncoding object or encoding name string that specifies the internal encoding to be used; if argumentext_enc is also given, it must be anEncoding object or encoding name string that specifies the external encoding to be used.

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

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

Optional keyword argumentsopts specify:

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

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

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

IO.pipe {|read_io,write_io|pread_io;pwrite_io }

Output:

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

Not available on all platforms.

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

rd,wr =IO.pipeifforkwr.closeputs"Parent got: <#{rd.read}>"rd.closeProcess.waitelserd.closeputs'Sending message to parent'wr.write"Hi Dad"wr.closeend

produces:

Sending message to parentParent got: <Hi Dad>
Source
static VALUErb_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);}

Executes the given commandcmd as a subprocess whose $stdin and $stdout are connected to a new streamio.

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

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

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

Optional argumentmode may be any valid IO mode. SeeAccess Modes.

Required argumentcmd determines which of the following occurs:

  • The process forks.

  • A specified program runs in a shell.

  • A specified program runs with specified arguments.

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

Each of these is detailed below.

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

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

Optional keyword argumentsopts specify:

Forked Process

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

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

Output:

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

Note that this is not supported on all platforms.

Shell Subprocess

When argumentcmd is a single string (but not'-'), the program namedcmd is run as a shell command:

IO.popen('uname')do|pipe|pipe.readlinesend

Output:

["Linux\n"]

Another example:

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

Output:

213

Program Subprocess

When argumentcmd is an array of strings, the program namedcmd[0] is run with all elements ofcmd as its arguments:

IO.popen(['du','..','.'])do|pipe|$stderr.putspipe.readlines.sizeend

Output:

1111

Program Subprocess withargv0

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

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

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

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

Example (sets$0 to ‘foo’):

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

Some Special Examples

# Set IO encoding.IO.popen("nkf -e filename",:external_encoding=>"EUC-JP") {|nkf_io|euc_jp_string =nkf_io.read}# Merge standard output and standard error using Kernel#spawn option. See Kernel#spawn.IO.popen(["ls","/",:err=>[:child,:out]])do|io|ls_result_with_error =io.readend# Use mixture of spawn options and IO options.IO.popen(["ls","/"],:err=>[:child,:out])do|io|ls_result_with_error =io.readendf =IO.popen("uname")pf.readlinesf.closeputs"Parent is #{Process.pid}"IO.popen("date") {|f|putsf.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;putsf.gets }

Output (from last section):

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

Raises exceptions thatIO.pipe andKernel.spawn raise.

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

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

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

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

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

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

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

With argumentlength, returnslength bytes if available:

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

With argumentslength andoffset, returnslength bytes if available, beginning at the givenoffset:

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

Optional keyword argumentsopts specify:

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

Returns an array of all lines read from the stream.

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

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

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

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

With argumentsep given, parses lines as determined by that line separator (seeLine Separator):

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

With argumentlimit given, parses lines as determined by the default line separator and the given line-length limit (seeLine Separator andLine Limit:

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

With argumentssep andlimit given, combines the two behaviors (seeLine Separator and Line Limit).

Optional keyword argumentsopts specify:

Source
static VALUErb_f_select(int argc, VALUE *argv, VALUE obj){    VALUE scheduler = rb_fiber_scheduler_current();    if (scheduler != Qnil) {        // It's optionally supported.        VALUE result = rb_fiber_scheduler_io_selectv(scheduler, argc, argv);        if (!UNDEF_P(result)) return result;    }    VALUE timeout;    struct select_args args;    struct timeval timerec;    int i;    rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);    if (NIL_P(timeout) || is_pos_inf(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);}

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

Not implemented on all platforms.

Each of the argumentsread_ios,write_ios, anderror_ios is an array ofIO objects.

Argumenttimeout is a numeric value (such as integer or float) timeout interval in seconds.timeout can also benil orFloat::INFINITY.nil andFloat::INFINITY means no timeout.

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

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

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

  • An array of the objects inerror_ios have pending exceptions.

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

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

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

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

beginresult =io_like.read_nonblock(maxlen)rescueIO::WaitReadableIO.select([io_like])retryrescueIO::WaitWritableIO.select(nil, [io_like])retryend

Especially, the combination of non-blocking methods and IO.select is preferred forIO like objects such asOpenSSL::SSL::SSLSocket. It hasto_io method to return underlyingIO object.IO.select callsto_io to obtain the file descriptor to wait.

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

The most likely situation is thatOpenSSL::SSL::SSLSocket buffers some data. IO.select doesn’t see the buffer. So IO.select can block whenOpenSSL::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 butOpenSSL::SSL::SSLSocket cannot decrypt a byte andOpenSSL::SSL::SSLSocket#readpartial will block.

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

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

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

Invoking IO.select beforeIO#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 usingwrite_nonblock andIO.select as follows:IO::WaitReadable should also be rescued for SSL renegotiation inOpenSSL::SSL::SSLSocket.

while0<string.bytesizebeginwritten =io_like.write_nonblock(string)rescueIO::WaitReadableIO.select([io_like])retryrescueIO::WaitWritableIO.select(nil, [io_like])retryendstring =string.byteslice(written..-1)end

Example:

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

Output:

pingpongpingpongpingpong(snipped)ping
Source
static VALUErb_io_s_sysopen(int argc, VALUE *argv, VALUE _){    VALUE fname, vmode, vperm;    VALUE intmode;    int oflags, fd;    mode_t perm;    rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);    FilePathValue(fname);    if (NIL_P(vmode))        oflags = O_RDONLY;    else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))        oflags = NUM2INT(intmode);    else {        StringValue(vmode);        oflags = rb_io_modestr_oflags(StringValueCStr(vmode));    }    if (NIL_P(vperm)) perm = 0666;    else              perm = NUM2MODET(vperm);    RB_GC_GUARD(fname) = rb_str_new4(fname);    fd = rb_sysopen(fname, oflags, perm);    return INT2NUM(fd);}

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

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

File.write('t.tmp','')# => 0IO.sysopen('t.tmp')# => 8IO.sysopen('t.tmp','w')# => 9
Source
static VALUErb_io_s_try_convert(VALUE dummy, VALUE io){    return rb_io_check_io(io);}

Attempts to convertobject into an IO object via methodto_io; returns the new IO object if successful, ornil otherwise:

IO.try_convert(STDOUT)# => #<IO:<STDOUT>>IO.try_convert(ARGF)# => #<IO:<STDIN>>IO.try_convert('STDOUT')# => nil
Source
static VALUErb_io_s_write(int argc, VALUE *argv, VALUE io){    return io_s_write(argc, argv, io, 0);}

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

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

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

With only argumentpath given, writes the givendata to the file at that path:

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

Ifoffset is zero (the default), the file is overwritten:

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

Ifoffset in within the file content, the file is partly overwritten:

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

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

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

Optional keyword argumentsopts specify:

Public Instance Methods

Source
VALUErb_io_addstr(VALUE io, VALUE str){    rb_io_write(io, str);    return io;}

Writes the givenobject toself, which must be opened for writing (seeAccess Modes); returnsself; ifobject is not a string, it is converted via methodto_s:

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

Output:

Hello, World!foobar2
Source
static VALUErb_io_advise(int argc, VALUE *argv, VALUE io){    VALUE advice, offset, len;    rb_off_t off, l;    rb_io_t *fptr;    rb_scan_args(argc, argv, "12", &advice, &offset, &len);    advice_arg_check(advice);    io = GetWriteIO(io);    GetOpenFile(io, fptr);    off = NIL_P(offset) ? 0 : NUM2OFFT(offset);    l   = NIL_P(len)    ? 0 : NUM2OFFT(len);#ifdef HAVE_POSIX_FADVISE    return do_io_advise(fptr, advice, off, l);#else    ((void)off, (void)l);       /* Ignore all hint */    return Qnil;#endif}

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

The arguments and results are platform-dependent.

The relevant data is specified by:

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

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

Argumentadvice is one of the following symbols:

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

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

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

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

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

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

Not implemented on all platforms.

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

Sets auto-close flag.

f =File.open(File::NULL)IO.for_fd(f.fileno).closef.gets# raises Errno::EBADFf =File.open(File::NULL)g =IO.for_fd(f.fileno)g.autoclose =falseg.closef.gets# won't cause Errno::EBADF
Source
static VALUErb_io_autoclose_p(VALUE io){    rb_io_t *fptr = RFILE(io)->fptr;    rb_io_check_closed(fptr);    return RBOOL(!(fptr->mode & FMODE_EXTERNAL));}

Returnstrue if the underlying file descriptor ofios will be closed at its finalization or at callingclose, otherwisefalse.

Source
static VALUEconsole_beep(VALUE io){#ifdef _WIN32    MessageBeep(0);#else    int fd = GetWriteFD(io);    if (write(fd, "\a", 1) < 0) sys_fail(io);#endif    return io;}

Beeps on the output console.

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

Source
static VALUErb_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;}

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

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

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

Returnstrue if the stream is on binary mode,false otherwise. SeeData Mode.

Source
static VALUEconsole_check_winsize_changed(VALUE io){    HANDLE h;    DWORD num;    h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));    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;}

Yields while console input events are queued.

This method is Windows only.

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

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

Clears the entire screen and moves the cursor top-left corner.

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

Source
static VALUErb_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;}

Closes the stream for both reading and writing if open for either or both; returnsnil. SeeOpen and Closed Streams.

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

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

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

Example:

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

Output:

falsepid 13760 exit 0true

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

Source
static VALUErb_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;}

Sets a close-on-exec flag.

f =File.open(File::NULL)f.close_on_exec =truesystem("cat","/proc/self/fd/#{f.fileno}")# cat: /proc/self/fd/3: No such file or directoryf.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.

Source
static VALUErb_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;}

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

f =File.open('t.txt')f.close_on_exec?# => truef.close_on_exec =falsef.close_on_exec?# => falsef.close
Source
static VALUErb_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);}

Closes the stream for reading if open for reading; returnsnil. SeeOpen and Closed Streams.

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

Example:

IO.popen('ruby','r+')do|pipe|putspipe.closed?pipe.close_writeputspipe.closed?pipe.close_readputs$?putspipe.closed?end

Output:

falsefalsepid 14748 exit 0true

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

Source
static VALUErb_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;}

Closes the stream for writing if open for writing; returnsnil. SeeOpen and Closed Streams.

Flushes any buffered writes to the operating system before closing.

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

IO.popen('ruby','r+')do|pipe|putspipe.closed?pipe.close_readputspipe.closed?pipe.close_writeputs$?putspipe.closed?end

Output:

falsefalsepid 15044 exit 0true

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

Source
VALUErb_io_closed_p(VALUE io){    rb_io_t *fptr;    VALUE write_io;    rb_io_t *write_fptr;    write_io = GetWriteIO(io);    if (io != write_io) {        write_fptr = RFILE(write_io)->fptr;        if (write_fptr && 0 <= write_fptr->fd) {            return Qfalse;        }    }    fptr = rb_io_get_fptr(io);    return RBOOL(0 > fptr->fd);}

Returnstrue if the stream is closed for both reading and writing,false otherwise. SeeOpen and Closed Streams.

IO.popen('ruby','r+')do|pipe|putspipe.closed?pipe.close_readputspipe.closed?pipe.close_writeputspipe.closed?end

Output:

falsefalsetrue

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

Source
static VALUEconsole_conmode_get(VALUE io){    conmode t;    int fd = GetReadFD(io);    if (!getattr(fd, &t)) sys_fail(io);    return conmode_new(cConmode, &t);}

Returns a data represents the current console mode.

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

Source
static VALUEconsole_conmode_set(VALUE io, VALUE mode){    conmode *t, r;    int fd = GetReadFD(io);    TypedData_Get_Struct(mode, conmode, &conmode_type, t);    r = *t;    if (!setattr(fd, &r)) sys_fail(io);    return mode;}

Sets the console mode tomode.

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

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

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

Source
static VALUEconsole_set_cooked(VALUE io){    conmode t;    int fd = GetReadFD(io);    if (!getattr(fd, &t)) sys_fail(io);    set_cookedmode(&t, NULL);    if (!setattr(fd, &t)) sys_fail(io);    return io;}

Enables cooked mode.

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

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

Source
static VALUEconsole_cursor_pos(VALUE io){#ifdef _WIN32    rb_console_size_t ws;    int fd = GetWriteFD(io);    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));#else    static const struct query_args query = {"\033[6n", 0};    VALUE resp = console_vt_response(0, 0, io, &query);    VALUE row, column, term;    unsigned int r, c;    if (!RB_TYPE_P(resp, T_ARRAY) || RARRAY_LEN(resp) != 3) return Qnil;    term = RARRAY_AREF(resp, 2);    if (!RB_TYPE_P(term, T_STRING) || RSTRING_LEN(term) != 1) return Qnil;    if (RSTRING_PTR(term)[0] != 'R') return Qnil;    row = RARRAY_AREF(resp, 0);    column = RARRAY_AREF(resp, 1);    rb_ary_resize(resp, 2);    r = NUM2UINT(row) - 1;    c = NUM2UINT(column) - 1;    RARRAY_ASET(resp, 0, INT2NUM(r));    RARRAY_ASET(resp, 1, INT2NUM(c));    return resp;#endif}

Returns the current cursor position as a two-element array of integers (row, column)

io.cursor# => [3, 5]

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

Source
static VALUEconsole_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));}

Same asio.goto(line, column)

SeeIO#goto.

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

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

Moves the cursor downn lines.

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

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

Moves the cursor leftn columns.

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

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

Moves the cursor rightn columns.

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

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

Moves the cursor upn lines.

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

Source
Also aliased as:each_line
Source
static VALUErb_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;}

Calls the given block with each byte (0..255) in the stream; returnsself. SeeByte IO.

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

Returns anEnumerator if no block is given.

Related:IO#each_char,IO#each_codepoint.

Source
static VALUErb_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;}

Calls the given block with each character in the stream; returnsself. SeeCharacter IO.

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

Returns anEnumerator if no block is given.

Related:IO#each_byte,IO#each_codepoint.

Source
static VALUErb_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_char_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);}

Calls the given block with each codepoint in the stream; returnsself:

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

Returns anEnumerator if no block is given.

Related:IO#each_byte,IO#each_char.

Calls the block with each remaining line read from the stream; returnsself. Does nothing if already at end-of-stream; SeeLine IO.

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

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

Output:

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

With only string argumentsep given, reads lines as determined by line separatorsep; seeLine Separator:

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

Output:

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

The two special values forsep are honored:

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

Output:

"First line\nSecond line\n\nFourth line\nFifth line\n"f.rewind# Get paragraphs (up to two line separators).f.each_line('') {|line|pline }

Output:

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

With only integer argumentlimit given, limits the number of bytes in each line; seeLine Limit:

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

Output:

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

With argumentssep andlimit given, combines the two behaviors (seeLine Separator and Line Limit).

Optional keyword argumentchomp specifies whether line separators are to be omitted:

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

Output:

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

Returns anEnumerator if no block is given.

Alias for:each
Source
static VALUEconsole_set_echo(VALUE io, VALUE f){    conmode t;    int fd = GetReadFD(io);    if (!getattr(fd, &t)) sys_fail(io);    if (RTEST(f))        set_echo(&t, NULL);    else        set_noecho(&t, NULL);    if (!setattr(fd, &t)) sys_fail(io);    return io;}

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.

Source
static VALUEconsole_echo_p(VALUE io){    conmode t;    int fd = GetReadFD(io);    if (!getattr(fd, &t)) sys_fail(io);    return echo_p(&t) ? Qtrue : Qfalse;}

Returnstrue if echo back is enabled.

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

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

Returnstrue if the stream is positioned at its end,false otherwise; seePosition:

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

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

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

r,w =IO.pipeThread.new {sleep1;w.close }r.eof?# => true # After 1-second wait.r,w =IO.pipeThread.new {sleep1;w.puts"a" }r.eof?# => false # After 1-second wait.r,w =IO.piper.eof?# blocks forever

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

Also aliased as:eof?
Alias for:eof
Source
static VALUEconsole_erase_line(VALUE io, VALUE val){    int mode = mode_in_range(val, 2, "line erase");#ifdef _WIN32    HANDLE h;    rb_console_size_t ws;    COORD *pos = &ws.dwCursorPosition;    DWORD w;    h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));    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;#else    rb_io_write(io, rb_sprintf(CSI "%dK", mode));#endif    return io;}

Erases the line at the cursor corresponding tomode.mode may be either: 0: after cursor 1: before and cursor 2: entire line

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

Source
static VALUEconsole_erase_screen(VALUE io, VALUE val){    int mode = mode_in_range(val, 3, "screen erase");#ifdef _WIN32    HANDLE h;    rb_console_size_t ws;    COORD *pos = &ws.dwCursorPosition;    DWORD w;    h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));    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);#else    rb_io_write(io, rb_sprintf(CSI "%dJ", mode));#endif    return io;}

Erases the screen at the cursor corresponding tomode.mode may be either: 0: after cursor 1: before and cursor 2: entire screen

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

Source
# File ext/pty/lib/expect.rb, line 33defexpect(pat,timeout=9999999)buf =''.dupcasepatwhenStringe_pat =Regexp.new(Regexp.quote(pat))whenRegexpe_pat =patelseraiseTypeError,"unsupported pattern class: #{pat.class}"end@unusedBuf||=''whiletrueifnot@unusedBuf.empty?c =@unusedBuf.slice!(0)elsif!IO.select([self],nil,nil,timeout)oreof?thenresult =nil@unusedBuf =bufbreakelsec =getcendbuf<<cif$expect_verboseSTDOUT.printcSTDOUT.flushendifmat=e_pat.match(buf)thenresult = [buf,*mat.captures]breakendendifblock_given?thenyieldresultelsereturnresultendnilend

Theexpect library adds instance methodIO#expect, which is similar to theTCL expect extension.

To use this method, you must requireexpect:

require'expect'

Reads from theIO until the givenpattern matches or thetimeout 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 givenpattern is obtained from theIO or the time specified as the timeout passes. An array is returned when the pattern is obtained from theIO. The first element of the array is the entire string obtained from theIO 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.

Source
static VALUErb_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));}

Returns theEncoding object that represents the encoding of the stream, ornil if the stream is in write mode and no encoding is specified.

SeeEncodings.

Source
static VALUErb_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);}

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

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

Not implemented on all platforms.

Source
static VALUErb_io_fdatasync(VALUE io){    rb_io_t *fptr;    io = GetWriteIO(io);    GetOpenFile(io, fptr);    if (io_fflush(fptr) < 0)        rb_sys_fail_on_write(fptr);    if ((int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)        return INT2FIX(0);    /* fall back */    return rb_io_fsync(io);}

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

Source
static VALUErb_io_fileno(VALUE io){    rb_io_t *fptr = RFILE(io)->fptr;    int fd;    rb_io_check_closed(fptr);    fd = fptr->fd;    return INT2FIX(fd);}

Returns the integer file descriptor for the stream:

$stdin.fileno# => 0$stdout.fileno# => 1$stderr.fileno# => 2File.open('t.txt').fileno# => 10f.close
Also aliased as:to_i
Source
VALUErb_io_flush(VALUE io){    return rb_io_flush_raw(io, 1);}

Flushes data buffered inself 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.
Source
static VALUErb_io_fsync(VALUE io){    rb_io_t *fptr;    io = GetWriteIO(io);    GetOpenFile(io, fptr);    if (io_fflush(fptr) < 0)        rb_sys_fail_on_write(fptr);    if ((int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))        rb_sys_fail_path(fptr->pathv);    return INT2FIX(0);}

Immediately writes to disk all data buffered in the stream, via the operating system’sfsync(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 supportfsync(2).

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

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

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

Related:IO#readbyte (may raiseEOFError).

Source
static VALUErb_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);}

Reads and returns the next 1-character string from the stream; returnsnil if already at end-of-stream. SeeCharacter IO.

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

Related:IO#readchar (may raiseEOFError).

Source
static VALUEconsole_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}

Reads and returns a character in raw mode.

SeeIO#raw for details on the parameters.

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

Source
static VALUEconsole_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);    rb_io_flush(wio);    str = rb_ensure(getpass_call, io, puts_call, wio);    return str_chomp(str);}

Reads and returns a line without echo back. Printsprompt unless it isnil.

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

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

require'io/console'IO::console.getpass("Enter password:")Enterpassword:# => "mypassword"
Source
static VALUErb_io_gets_m(int argc, VALUE *argv, VALUE io){    VALUE str;    str = rb_io_getline(argc, argv, io);    rb_lastline_set(str);    return str;}

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

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

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

With only string argumentsep given, returns the next line as determined by line separatorsep, ornil if none; seeLine Separator:

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

The two special values forsep are honored:

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

With only integer argumentlimit given, limits the number of bytes in the line; seeLine Limit:

# No more than one line.File.open('t.txt') {|f|f.gets(10) }# => "First line"File.open('t.txt') {|f|f.gets(11) }# => "First line\n"File.open('t.txt') {|f|f.gets(12) }# => "First line\n"

With argumentssep andlimit given, combines the two behaviors (seeLine Separator and Line Limit).

Optional keyword argumentchomp specifies whether line separators are to be omitted:

f =File.open('t.txt')# Chomp the lines.f.gets(chomp:true)# => "First line"f.gets(chomp:true)# => "Second line"f.gets(chomp:true)# => ""f.gets(chomp:true)# => "Fourth line"f.gets(chomp:true)# => "Fifth line"f.gets(chomp:true)# => nilf.close
Source
static VALUEconsole_goto(VALUE io, VALUE y, VALUE x){#ifdef _WIN32    COORD pos;    int fd = GetWriteFD(io);    pos.X = NUM2UINT(x);    pos.Y = NUM2UINT(y);    if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) {        rb_syserr_fail(LAST_ERROR, 0);    }#else    rb_io_write(io, rb_sprintf(CSI "%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1));#endif    return io;}

Set the cursor position atline andcolumn.

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

Source
static VALUEconsole_goto_column(VALUE io, VALUE val){#ifdef _WIN32    HANDLE h;    rb_console_size_t ws;    COORD *pos = &ws.dwCursorPosition;    h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));    if (!GetConsoleScreenBufferInfo(h, &ws)) {        rb_syserr_fail(LAST_ERROR, 0);    }    pos->X = NUM2INT(val);    if (!SetConsoleCursorPosition(h, *pos)) {        rb_syserr_fail(LAST_ERROR, 0);    }#else    rb_io_write(io, rb_sprintf(CSI "%dG", NUM2UINT(val)+1));#endif    return io;}

Set the cursor position atcolumn in the same line of the current position.

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

Source
static VALUEconsole_iflush(VALUE io){#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H    int fd = GetReadFD(io);    if (tcflush(fd, TCIFLUSH)) sys_fail(io);#endif    return io;}

Flushes input buffer in kernel.

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

Source
static VALUErb_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, ">");}

Returns a string representation ofself:

f =File.open('t.txt')f.inspect# => "#<File:t.txt>"f.close
Source
static VALUErb_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));}

Returns theEncoding object that represents the encoding of the internal string, if conversion is specified, ornil otherwise.

SeeEncodings.

Source
static VALUErb_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);}

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

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

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

Not implemented on all platforms.

Source
static VALUEconsole_ioflush(VALUE io){#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H    int fd1 = GetReadFD(io);    int fd2 = GetWriteFD(io);    if (fd2 != -1 && fd1 != fd2) {        if (tcflush(fd1, TCIFLUSH)) sys_fail(io);        if (tcflush(fd2, TCOFLUSH)) sys_fail(io);    }    else {        if (tcflush(fd1, TCIOFLUSH)) sys_fail(io);    }#endif    return io;}

Flushes input and output buffers in kernel.

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

Source
static VALUErb_io_isatty(VALUE io){    rb_io_t *fptr;    GetOpenFile(io, fptr);    return RBOOL(isatty(fptr->fd) != 0);}

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

f =File.new('t.txt').isatty#=> falsef.closef =File.new('/dev/tty').isatty#=> truef.close
Also aliased as:tty?
Source
static VALUErb_io_lineno(VALUE io){    rb_io_t *fptr;    GetOpenFile(io, fptr);    rb_io_check_char_readable(fptr);    return INT2NUM(fptr->lineno);}

Returns the current line number for the stream; seeLine Number.

Source
static VALUErb_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;}

Sets and returns the line number for the stream; seeLine Number.

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

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

Source
static VALUErb_io_nonblock_block(int argc, VALUE *argv, VALUE self){    int nb = 1;    int descriptor = rb_io_descriptor(self);    if (argc > 0) {        VALUE v;        rb_scan_args(argc, argv, "01", &v);        nb = RTEST(v);    }    int current_flags = get_fcntl_flags(descriptor);    int restore[2] = {descriptor, current_flags};    if (!io_nonblock_set(descriptor, current_flags, nb))        return rb_yield(self);    return rb_ensure(rb_yield, self, io_nonblock_restore, (VALUE)restore);}

Yieldsself in non-blocking mode.

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

Source
static VALUErb_io_nonblock_set(VALUE self, VALUE value){    if (RTEST(value)) {        rb_io_t *fptr;        GetOpenFile(self, fptr);        rb_io_set_nonblock(fptr);    }    else {        int descriptor = rb_io_descriptor(self);        io_nonblock_set(descriptor, get_fcntl_flags(descriptor), RTEST(value));    }    return self;}

Enables non-blocking mode on a stream when set totrue, and blocking mode when set tofalse.

This method set or clear O_NONBLOCK flag for the file descriptor inios.

The behavior of mostIO methods is not affected by this flag because they retry system calls to complete their task after EAGAIN and partial read/write. (An exception isIO#syswrite which doesn’t retry.)

This method can be used to clear non-blocking mode of standard I/O. Since nonblocking methods (read_nonblock, etc.) set non-blocking mode but they doesn’t clear it, this method is usable as follows.

END {STDOUT.nonblock =false }STDOUT.write_nonblock("foo")

Since the flag is shared across processes and many non-Ruby commands doesn’t expect standard I/O with non-blocking mode, it would be safe to clear the flag before Ruby program exits.

For example following Ruby program leaves STDIN/STDOUT/STDER non-blocking mode. (STDIN, STDOUT and STDERR are connected to a terminal. So making one of them nonblocking-mode effects other two.) Thus cat command try to read from standard input and it causes “Resource temporarily unavailable” error (EAGAIN).

% ruby -e 'STDOUT.write_nonblock("foo\n")'; catfoocat: -: Resource temporarily unavailable

Clearing the flag makes the behavior of cat command normal. (cat command waits input from standard input.)

% ruby -rio/nonblock -e 'END { STDOUT.nonblock = false }STDOUT.write_nonblock("foo")'; catfoo
Source
static VALUErb_io_nonblock_p(VALUE io){    if (get_fcntl_flags(rb_io_descriptor(io)) & O_NONBLOCK)        return Qtrue;    return Qfalse;}

Returnstrue if anIO object is in non-blocking mode.

Source
static VALUEio_nread(VALUE io){    rb_io_t *fptr;    int len;    ioctl_arg n;    GetOpenFile(io, fptr);    rb_io_check_char_readable(fptr);    len = rb_io_read_pending(fptr);    if (len > 0) return INT2FIX(len);#ifdef HAVE_RB_IO_DESCRIPTOR    int fd = rb_io_descriptor(io);#else    int fd = fptr->fd;#endif    if (!FIONREAD_POSSIBLE_P(fd)) return INT2FIX(0);    if (ioctl(fd, FIONREAD, &n)) return INT2FIX(0);    if (n > 0) return ioctl_arg2num(n);    return INT2FIX(0);}

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

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

Source
static VALUEconsole_oflush(VALUE io){    int fd = GetWriteFD(io);#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H    if (tcflush(fd, TCOFLUSH)) sys_fail(io);#endif    (void)fd;    return io;}

Flushes output buffer in kernel.

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

Source
VALUErb_io_path(VALUE io){    rb_io_t *fptr = RFILE(io)->fptr;    if (!fptr)        return Qnil;    return rb_obj_dup(fptr->pathv);}

Returns the path associated with theIO, ornil if there is no path associated with theIO. It is not guaranteed that the path exists on the filesystem.

$stdin.path# => "<STDIN>"File.open("testfile") {|f|f.path}# => "testfile"
Also aliased as:to_path
Source
static VALUEio_pathconf(VALUE io, VALUE arg){    int name;    long ret;    name = NUM2INT(arg);    errno = 0;    ret = fpathconf(rb_io_descriptor(io), name);    if (ret == -1) {        if (errno == 0) /* no limit */            return Qnil;        rb_sys_fail("fpathconf");    }    return LONG2NUM(ret);}

Returns pathname configuration variable using fpathconf().

name should be a constant underEtc which begins withPC_.

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|pw.pathconf(Etc::PC_PIPE_BUF)#=> 4096}
Source
static VALUErb_io_pid(VALUE io){    rb_io_t *fptr;    GetOpenFile(io, fptr);    if (!fptr->pid)        return Qnil;    return PIDT2NUM(fptr->pid);}

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

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

Output:

In child, pid is 26209In parent, child pid is 26209
Alias for:tell
Source
static VALUErb_io_set_pos(VALUE io, VALUE offset){    rb_io_t *fptr;    rb_off_t pos;    pos = NUM2OFFT(offset);    GetOpenFile(io, fptr);    pos = io_seek(fptr, pos, SEEK_SET);    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);    return OFFT2NUM(pos);}

Seeks to the givennew_position (in bytes); seePosition:

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

Related:IO#seek,IO#tell.

Source
static VALUErb_io_pread(int argc, VALUE *argv, VALUE io){    VALUE len, offset, str;    rb_io_t *fptr;    ssize_t n;    struct prdwr_internal_arg arg;    int shrinkable;    rb_scan_args(argc, argv, "21", &len, &offset, &str);    arg.count = NUM2SIZET(len);    arg.offset = NUM2OFFT(offset);    shrinkable = io_setstrbuf(&str, (long)arg.count);    if (arg.count == 0) return str;    arg.buf = RSTRING_PTR(str);    GetOpenFile(io, fptr);    rb_io_check_byte_readable(fptr);    arg.io = fptr;    arg.fd = fptr->fd;    rb_io_check_closed(fptr);    rb_str_locktmp(str);    n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);    if (n < 0) {        rb_sys_fail_path(fptr->pathv);    }    io_set_read_length(str, n, shrinkable);    if (n == 0 && arg.count > 0) {        rb_eof_error();    }    return str;}

Behaves likeIO#readpartial, except that it:

  • Reads at the givenoffset (in bytes).

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

  • Bypasses any user space buffering in the stream.

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

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

Not available on some platforms.

Source
static VALUEconsole_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;}

Returnstrue ifkey is pressed.key may be a virtual key code or its name (String orSymbol) with out “VK_” prefix.

This method is Windows only.

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

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

Writes the given objects to the stream; returnsnil. Appends the output record separator$OUTPUT_RECORD_SEPARATOR ($\), if it is notnil. SeeLine IO.

With argumentobjects given, for each object:

  • Converts via its methodto_s if not a string.

  • Writes to the stream.

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

With default separators:

f =File.open('t.tmp','w+')objects = [0,0.0,Rational(0,1),Complex(0,0),:zero,'zero']p$OUTPUT_RECORD_SEPARATORp$OUTPUT_FIELD_SEPARATORf.print(*objects)f.rewindpf.readf.close

Output:

nilnil"00.00/10+0izerozero"

With specified separators:

$\ ="\n"$, =','f.rewindf.print(*objects)f.rewindpf.read

Output:

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

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

f =File.open('t.tmp','w+')gets# Sets $_ to the most recent user input.f.printf.close
Source
VALUErb_io_printf(int argc, const VALUE *argv, VALUE out){    rb_io_write(out, rb_f_sprintf(argc, argv));    return Qnil;}

Formats and writesobjects to the stream.

For details onformat_string, seeFormat Specifications.

Source
static VALUErb_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;}

Writes a character to the stream. SeeCharacter IO.

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

$stdout.putc"A"$stdout.putc65

Output:

AA
Source
VALUErb_io_puts(int argc, const VALUE *argv, VALUE out){    VALUE line, args[2];    /* if no argument given, print newline. */    if (argc == 0) {        rb_io_write(out, rb_default_rs);        return Qnil;    }    for (int i = 0; i < argc; i++) {        // Convert the argument to a string:        if (RB_TYPE_P(argv[i], T_STRING)) {            line = argv[i];        }        else if (rb_exec_recursive(io_puts_ary, argv[i], out)) {            continue;        }        else {            line = rb_obj_as_string(argv[i]);        }        // Write the line:        int n = 0;        if (RSTRING_LEN(line) == 0) {            args[n++] = rb_default_rs;        }        else {            args[n++] = line;            if (!rb_str_end_with_asciichar(line, '\n')) {                args[n++] = rb_default_rs;            }        }        rb_io_writev(out, n, args);    }    return Qnil;}

Writes the givenobjects to the stream, which must be open for writing; returnsnil.\ Writes a newline after each that does not already end with a newline sequence. If called without arguments, writes a newline. SeeLine IO.

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

Treatment for each object:

  • String: writes the string.

  • Neither string nor array: writesobject.to_s.

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

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

defshow(*objects)# Puts objects to file.f =File.new('t.tmp','w+')f.puts(objects)# Return file content.f.rewindpf.readf.closeend# Strings without newlines.show('foo','bar','baz')# => "foo\nbar\nbaz\n"# Strings, some with newlines.show("foo\n",'bar',"baz\n")# => "foo\nbar\nbaz\n"# Neither strings nor arrays:show(0,0.0,Rational(0,1),Complex(9,0),:zero)# => "0\n0.0\n0/1\n9+0i\nzero\n"# Array of strings.show(['foo',"bar\n",'baz'])# => "foo\nbar\nbaz\n"# Nested arrays.show([[[0,1],2,3],4,5])# => "0\n1\n2\n3\n4\n5\n"
Source
static VALUErb_io_pwrite(VALUE io, VALUE str, VALUE offset){    rb_io_t *fptr;    ssize_t n;    struct prdwr_internal_arg arg;    VALUE tmp;    if (!RB_TYPE_P(str, T_STRING))        str = rb_obj_as_string(str);    arg.offset = NUM2OFFT(offset);    io = GetWriteIO(io);    GetOpenFile(io, fptr);    rb_io_check_writable(fptr);    arg.io = fptr;    arg.fd = fptr->fd;    tmp = rb_str_tmp_frozen_acquire(str);    arg.buf = RSTRING_PTR(tmp);    arg.count = (size_t)RSTRING_LEN(tmp);    n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg, RUBY_IO_WRITABLE);    if (n < 0) rb_sys_fail_path(fptr->pathv);    rb_str_tmp_frozen_release(str, tmp);    return SSIZET2NUM(n);}

Behaves likeIO#write, except that it:

  • Writes at the givenoffset (in bytes).

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

  • Bypasses any user space buffering in the stream.

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

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

Not available on some platforms.

Source
static VALUEconsole_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);}

Yieldsself 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 parametermin specifies the minimum number of bytes that should be received when a read operation is performed. (default: 1)

The parametertime specifies the timeout inseconds with a precision of 1/10 of a second. (default: 0)

If the parameterintr istrue, 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.

Source
static VALUEconsole_set_raw(int argc, VALUE *argv, VALUE io){    conmode t;    rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);    int fd = GetReadFD(io);    if (!getattr(fd, &t)) sys_fail(io);    set_rawmode(&t, optp);    if (!setattr(fd, &t)) sys_fail(io);    return io;}

Enables raw mode, and returnsio.

If the terminal mode needs to be back, useio.raw { ... }.

SeeIO#raw for details on the parameters.

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

Source
static VALUEio_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;}

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

  • Ifmaxlen isnil, reads all bytes using the stream’s data mode.

  • Otherwise reads up tomaxlen bytes in binary mode.

Returns a string (either a new string or the givenout_string) containing the bytes read. The encoding of the string depends on bothmaxLen andout_string:

  • maxlen isnil: uses internal encoding ofself (regardless of whetherout_string was given).

  • maxlen notnil:

    • out_string given: encoding ofout_string not modified.

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

Without Argumentout_string

When argumentout_string is omitted, the returned value is a new string:

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

Ifmaxlen is zero, returns an empty string.

With Argumentout_string

When argumentout_string is given, the returned value isout_string, whose content is replaced:

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

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

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

If you need the behavior like a single read(2) system call, considerreadpartial,read_nonblock, andsysread.

Related:IO#write.

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

Reads at mostmaxlen bytes fromios using the read(2) system call after O_NONBLOCK is set for the underlying file descriptor.

If the optionaloutbuf argument is present, it must reference aString, which will receive the data. Theoutbuf 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 byIO::WaitReadable. SoIO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.

read_nonblock causesEOFError on EOF.

On some platforms, such as Windows, non-blocking mode is not supported onIO 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.

Whenread_nonblock raises an exception kind ofIO::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).beginresult =io.read_nonblock(maxlen)rescueIO::WaitReadableIO.select([io])retryend

AlthoughIO#read_nonblock doesn’t raiseIO::WaitWritable.OpenSSL::Buffering#read_nonblock can raiseIO::WaitWritable. IfIO and SSL should be used polymorphically,IO::WaitWritable should be rescued too. See the document ofOpenSSL::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 argumentexception tofalse, you can indicate thatread_nonblock should not raise anIO::WaitReadable exception, but return the symbol:wait_readable instead. At EOF, it will return nil instead of raisingEOFError.

Source
static VALUErb_io_readbyte(VALUE io){    VALUE c = rb_io_getbyte(io);    if (NIL_P(c)) {        rb_eof_error();    }    return c;}

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

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

Related:IO#getbyte (will not raiseEOFError).

Source
static VALUErb_io_readchar(VALUE io){    VALUE c = rb_io_getc(io);    if (NIL_P(c)) {        rb_eof_error();    }    return c;}

Reads and returns the next 1-character string from the stream; raisesEOFError if already at end-of-stream. SeeCharacter IO.

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

Related:IO#getc (will not raiseEOFError).

Source
# File io.rb, line 133defreadline(sep =$/,limit =nil,chomp:false)Primitive.io_readline(sep,limit,chomp)end

Reads a line as withIO#gets, but raisesEOFError if already at end-of-stream.

Optional keyword argumentchomp specifies whether line separators are to be omitted.

Source
static VALUErb_io_readlines(int argc, VALUE *argv, VALUE io){    struct getline_arg args;    prepare_getline_args(argc, argv, &args, io);    return io_readlines(&args, io);}

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

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

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

With only string argumentsep given, returns lines as determined by line separatorsep, ornil if none; seeLine Separator:

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

The two special values forsep are honored:

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

With only integer argumentlimit given, limits the number of bytes in each line; seeLine Limit:

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

With argumentssep andlimit given, combines the two behaviors (seeLine Separator and Line Limit).

Optional keyword argumentchomp specifies whether line separators are to be omitted:

f =File.new('t.txt')f.readlines(chomp:true)# => ["First line", "Second line", "", "Fourth line", "Fifth line"]f.close
Source
static VALUEio_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;}

Reads up tomaxlen bytes from the stream; returns a string (either a new string or the givenout_string). Its encoding is:

  • The unchanged encoding ofout_string, ifout_string is given.

  • ASCII-8BIT, otherwise.

  • Containsmaxlen 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 argumentmaxlen given, returns a new string:

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

With both argumentmaxlen and string argumentout_string given, returns modifiedout_string:

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

This method is useful for a stream such as a pipe, a socket, or a tty. It blocks only when no data is immediately available. This means that it blocks only whenall 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 raisesEOFError.

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 raisesEOFError 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 bufferedIO (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 situationIO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.

Examples:

#                        # Returned      Buffer Content    Pipe Contentr,w =IO.pipe#w<<'abc'#               ""                "abc".r.readpartial(4096)# => "abc"      ""                ""r.readpartial(4096)# (Blocks because buffer and pipe are empty.)#                        # Returned      Buffer Content    Pipe Contentr,w =IO.pipe#w<<'abc'#               ""                "abc"w.close#               ""                "abc" EOFr.readpartial(4096)# => "abc"      ""                 EOFr.readpartial(4096)# raises EOFError#                        # Returned      Buffer Content    Pipe Contentr,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"    ""                ""
Source
static VALUEio_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_char_readable(fptr);    if (rb_io_read_pending(fptr)) return Qtrue;#ifndef HAVE_RB_IO_WAIT    return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse;#else    return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1);#endif}

Returns a truthy value if input available without blocking, or a falsy value.

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

Source
static VALUErb_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)) {        enum rb_io_mode fmode;        struct rb_io_encoding convconfig;        rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);        if (RUBY_IO_EXTERNAL_P(fptr) &&            ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=            (fptr->mode & FMODE_READWRITE)) {            rb_raise(rb_eArgError,                     "%s can't change access mode from \"%s\" to \"%s\"",                     PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),                     rb_io_fmode_modestr(fmode));        }        fptr->mode = fmode;        fptr->encs = convconfig;    }    else {        oflags = rb_io_fmode_oflags(fptr->mode);    }    fptr->pathv = fname;    if (fptr->fd < 0) {        fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);        fptr->stdio_file = 0;        return file;    }    if (fptr->mode & FMODE_WRITABLE) {        if (io_fflush(fptr) < 0)            rb_sys_fail_on_write(fptr);    }    fptr->rbuf.off = fptr->rbuf.len = 0;    if (fptr->stdio_file) {        int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),                           rb_io_oflags_modestr(oflags),                           fptr->stdio_file);        if (e) rb_syserr_fail_path(e, fptr->pathv);        fptr->fd = fileno(fptr->stdio_file);        rb_fd_fix_cloexec(fptr->fd);#ifdef USE_SETVBUF        if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)            rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);#endif        if (fptr->stdio_file == stderr) {            if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)                rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);        }        else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {            if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)                rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);        }    }    else {        int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);        int err = 0;        if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)            err = errno;        (void)close(tmpfd);        if (err) {            rb_syserr_fail_path(err, fptr->pathv);        }    }    return file;}

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

With argumentother_io given, reassociates with that stream:

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

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

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

Optional keyword argumentsopts specify:

Source
static VALUErb_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);}

Repositions the stream to its beginning, setting both the position and the line number to zero; seePosition andLine Number:

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

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

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

Scrolls the entire scrolls backwardn lines.

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

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

Scrolls the entire scrolls forwardn lines.

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

Source
static VALUErb_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);}

Seeks to the position given by integeroffset (seePosition) and constantwhence, which is one of:

  • :CUR orIO::SEEK_CUR: Repositions the stream to its current position plus the givenoffset:

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

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

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

Related:IO#pos=,IO#tell.

Source
static VALUErb_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;}

SeeEncodings.

Argumentext_enc, if given, must be anEncoding object or aString with the encoding name; it is assigned as the encoding for the stream.

Argumentint_enc, if given, must be anEncoding object or aString with the encoding name; it is assigned as the encoding for the internal string.

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

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

Optional keyword argumentsenc_opts specifyEncoding options.

Source
static VALUErb_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);}

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

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

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

Source
static VALUErb_io_stat(VALUE obj){    rb_io_t *fptr;    rb_io_stat_data st;    GetOpenFile(obj, fptr);    if (fstatx_without_gvl(fptr, &st, STATX_ALL) == -1) {        rb_sys_fail_path(fptr->pathv);    }    return rb_statx_new(&st);}

Returns status information forios as an object of typeFile::Stat.

f =File.new("testfile")s =f.stat"%o"%s.mode#=> "100644"s.blksize#=> 4096s.atime#=> Wed Apr 09 08:53:54 CDT 2003
Source
static VALUErb_io_sync(VALUE io){    rb_io_t *fptr;    io = GetWriteIO(io);    GetOpenFile(io, fptr);    return RBOOL(fptr->mode & FMODE_SYNC);}

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

f =File.open('t.tmp','w')f.sync# => falsef.sync =truef.sync# => truef.close
Source
static VALUErb_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;}

Sets thesyncmode 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# => falsef.sync =truef.sync# => truef.close

Related:IO#fsync.

Source
static VALUErb_io_sysread(int argc, VALUE *argv, VALUE io){    VALUE len, str;    rb_io_t *fptr;    long n, ilen;    struct io_internal_read_struct iis;    int shrinkable;    rb_scan_args(argc, argv, "11", &len, &str);    ilen = NUM2LONG(len);    shrinkable = io_setstrbuf(&str, ilen);    if (ilen == 0) return str;    GetOpenFile(io, fptr);    rb_io_check_byte_readable(fptr);    if (READ_DATA_BUFFERED(fptr)) {        rb_raise(rb_eIOError, "sysread for buffered IO");    }    rb_io_check_closed(fptr);    io_setstrbuf(&str, ilen);    iis.th = rb_thread_current();    iis.fptr = fptr;    iis.nonblock = 0;    iis.fd = fptr->fd;    iis.buf = RSTRING_PTR(str);    iis.capa = ilen;    iis.timeout = NULL;    n = io_read_memory_locktmp(str, &iis);    if (n < 0) {        rb_sys_fail_path(fptr->pathv);    }    io_set_read_length(str, n, shrinkable);    if (n == 0 && ilen > 0) {        rb_eof_error();    }    return str;}

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

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

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

Behaves likeIO#seek, except that it:

  • Uses low-level system functions.

  • Returns the new position.

Source
static VALUErb_io_syswrite(VALUE io, VALUE str){    VALUE tmp;    rb_io_t *fptr;    long n, len;    const char *ptr;    if (!RB_TYPE_P(str, T_STRING))        str = rb_obj_as_string(str);    io = GetWriteIO(io);    GetOpenFile(io, fptr);    rb_io_check_writable(fptr);    if (fptr->wbuf.len) {        rb_warn("syswrite for buffered IO");    }    tmp = rb_str_tmp_frozen_acquire(str);    RSTRING_GETMEM(tmp, ptr, len);    n = rb_io_write_memory(fptr, ptr, len);    if (n < 0) rb_sys_fail_path(fptr->pathv);    rb_str_tmp_frozen_release(str, tmp);    return LONG2FIX(n);}

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

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

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

Source
static VALUErb_io_tell(VALUE io){    rb_io_t *fptr;    rb_off_t pos;    GetOpenFile(io, fptr);    pos = io_tell(fptr);    if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);    pos -= fptr->rbuf.len;    return OFFT2NUM(pos);}

Returns the current position (in bytes) inself (seePosition):

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

Related:IO#pos=,IO#seek.

Also aliased as:pos
Source
VALUErb_io_timeout(VALUE self){    rb_io_t *fptr = rb_io_get_fptr(self);    return fptr->timeout;}

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

Source
VALUErb_io_set_timeout(VALUE self, VALUE timeout){    // Validate it:    if (RTEST(timeout)) {        rb_time_interval(timeout);    }    rb_io_t *fptr = rb_io_get_fptr(self);    fptr->timeout = timeout;    return self;}

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

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

This affects the following methods (but is not limited to):gets,puts,read,write,wait_readable andwait_writable. This also affects blocking socket operations likeSocket#accept andSocket#connect.

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

Alias for:fileno
Source
static VALUErb_io_to_io(VALUE io){    return io;}

Returnsself.

Alias for:path
Alias for:isatty
Source
static VALUEconsole_ttyname(VALUE io){    int fd = rb_io_descriptor(io);    if (!isatty(fd)) return Qnil;# if defined _WIN32    return rb_usascii_str_new_lit("con");# elif defined HAVE_TTYNAME_R    {        char termname[1024], *tn = termname;        size_t size = sizeof(termname);        int e;        if (ttyname_r(fd, tn, size) == 0)            return rb_interned_str_cstr(tn);        if ((e = errno) == ERANGE) {            VALUE s = rb_str_new(0, size);            while (1) {                tn = RSTRING_PTR(s);                size = rb_str_capacity(s);                if (ttyname_r(fd, tn, size) == 0) {                    return rb_str_to_interned_str(rb_str_resize(s, strlen(tn)));                }                if ((e = errno) != ERANGE) break;                if ((size *= 2) >= INT_MAX/2) break;                rb_str_resize(s, size);            }        }        rb_syserr_fail_str(e, rb_sprintf("ttyname_r(%d)", fd));        UNREACHABLE_RETURN(Qnil);    }# elif defined HAVE_TTYNAME    {        const char *tn = ttyname(fd);        if (!tn) {            int e = errno;            rb_syserr_fail_str(e, rb_sprintf("ttyname(%d)", fd));        }        return rb_interned_str_cstr(tn);    }# else#   error No ttyname function# endif}

Returns name of associated terminal (tty) ifio is not a tty. Returnsnil otherwise.

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

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

Note that:

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

  • Callingrewind on the stream discards the pushed-back data.

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

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

When argumentstring is given, uses all bytes:

File.write('t.tmp','012')f =File.open('t.tmp')f.ungetbyte('A')# => nilf.read# => "A012"f.rewindf.ungetbyte('BCDE')# => nilf.read# => "BCDE012"f.close
Source
VALUErb_io_ungetc(VALUE io, VALUE c){    rb_io_t *fptr;    long len;    GetOpenFile(io, fptr);    rb_io_check_char_readable(fptr);    if (FIXNUM_P(c)) {        c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));    }    else if (RB_BIGNUM_TYPE_P(c)) {        c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));    }    else {        StringValue(c);    }    if (NEED_READCONV(fptr)) {        SET_BINARY_MODE(fptr);        len = RSTRING_LEN(c);#if SIZEOF_LONG > SIZEOF_INT        if (len > INT_MAX)            rb_raise(rb_eIOError, "ungetc failed");#endif        make_readconv(fptr, (int)len);        if (fptr->cbuf.capa - fptr->cbuf.len < len)            rb_raise(rb_eIOError, "ungetc failed");        if (fptr->cbuf.off < len) {            MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,                    fptr->cbuf.ptr+fptr->cbuf.off,                    char, fptr->cbuf.len);            fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;        }        fptr->cbuf.off -= (int)len;        fptr->cbuf.len += (int)len;        MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);    }    else {        NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);        io_ungetbyte(c, fptr);    }    return Qnil;}

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

Note that:

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

  • Callingrewind on the stream discards the pushed-back data.

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

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

When argumentstring is given, uses all characters:

File.write('t.tmp','012')f =File.open('t.tmp')f.ungetc('A')# => nilf.read# => "A012"f.rewindf.ungetc("\u0442\u0435\u0441\u0442")# => nilf.getc.ord# => 1090f.getc.ord# => 1077f.getc.ord# => 1089f.getc.ord# => 1090f.close
Source
static VALUEio_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;    int i, return_io = 0;    if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {        /* We'd prefer to return the actual mask, but this form would return the io itself: */        return_io = 1;        /* Slow/messy path: */        for (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;        if (events == 0) {            events = RUBY_IO_READABLE;        }    }    else /* argc == 2 and neither are symbols */ {        /* This is the fast path: */        events = io_event_from_value(argv[0]);        timeout = argv[1];    }    if (events & RUBY_IO_READABLE) {        rb_io_t *fptr = NULL;        RB_IO_POINTER(io, fptr);        if (rb_io_read_pending(fptr)) {            /* This was the original behaviour: */            if (return_io) return Qtrue;            /* New behaviour always returns an event mask: */            else return RB_INT2NUM(RUBY_IO_READABLE);        }    }    return io_wait_event(io, events, timeout, return_io);#endif}

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

The events can be a bit mask ofIO::READABLE,IO::WRITABLE orIO::PRIORITY.

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

The second form: if one or more event symbols (:read,:write, or:read_write) are passed, the event mask is the bit OR of the bitmask corresponding to those symbols. In this form,timeout is optional, the order of the arguments is arbitrary, and returnsio if any of the events is ready.

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

Also aliased as: wait
Source
static VALUEio_wait_priority(int argc, VALUE *argv, VALUE io){    rb_io_t *fptr = NULL;    RB_IO_POINTER(io, fptr);    rb_io_check_char_readable(fptr);    if (rb_io_read_pending(fptr)) return Qtrue;    rb_check_arity(argc, 0, 1);    VALUE timeout = argc == 1 ? argv[0] : Qnil;    return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);}

Waits untilIO is priority and returns a truthy value or a falsy value when times out. Priority data is sent and received using the Socket::MSG_OOB flag and is typically limited to streams.

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

Also aliased as: wait_priority
Source
static VALUEio_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_char_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, 1);#endif}

Waits untilIO is readable and returns a truthy value, or a falsy value when times out. Returns a truthy value immediately when buffered data is available.

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

Also aliased as: wait_readable
Source
static VALUEio_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, 1);#endif}

Waits untilIO is writable and returns a truthy value or a falsy value when times out.

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

Also aliased as: wait_writable
Source
static VALUEconsole_winsize(VALUE io){    rb_console_size_t ws;    int fd = GetWriteFD(io);    if (!getwinsize(fd, &ws)) sys_fail(io);    return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));}

Returns console size.

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

Source
static VALUEconsole_set_winsize(VALUE io, VALUE size){    rb_console_size_t ws;#if defined _WIN32    HANDLE wh;    int newrow, newcol;    BOOL ret;#endif    VALUE row, col, xpixel, ypixel;    const VALUE *sz;    long sizelen;    int fd;    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(io);#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(io);#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;}

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

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

Source
static VALUEio_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);    }}

Writes each of the givenobjects toself, which must be opened for writing (seeAccess Modes); returns the total number bytes written; each ofobjects that is not a string is converted via methodto_s:

$stdout.write('Hello',', ','World!',"\n")# => 14$stdout.write('foo',:bar,2,"\n")# => 8

Output:

Hello, World!foobar2

Related:IO#read.

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

Writes the given string toios 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 byIO::WaitWritable. SoIO::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"*100000pw.write_nonblock(s)#=> 65536# write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).pw.write_nonblock("b")# Resource temporarily unavailable (Errno::EAGAIN)

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

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

beginresult =io.write_nonblock(string)rescueIO::WaitWritable,Errno::EINTRIO.select(nil, [io])retryend

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 theIO object. In such cases,write_nonblock raisesErrno::EBADF.

By specifying a keyword argumentexception tofalse, you can indicate thatwrite_nonblock should not raise anIO::WaitWritable exception, but return the symbol:wait_writable instead.