Class: IO

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

Overview

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

Many of the examples in this section use class File, the only standard subclass of IO. The two classes are closely associated.

As used in this section, portname may take any of the following forms.

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

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

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

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

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

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

I/O ports may be opened in any one of several different modes, which are shown in this section as mode. The mode may either be a Fixnum or a String. If numeric, it should be one of the operating system specific constants (O_RDONLY, O_WRONLY, O_RDWR, O_APPEND and so on). See man open(2) for more information.

If the mode is given as a String, it must be one of the values listed in the following table.

Mode |  Meaning
-----+--------------------------------------------------------
"r"  |  Read-only, starts at beginning of file  (default mode).
-----+--------------------------------------------------------
"r+" |  Read-write, starts at beginning of file.
-----+--------------------------------------------------------
"w"  |  Write-only, truncates existing file
     |  to zero length or creates a new file for writing.
-----+--------------------------------------------------------
"w+" |  Read-write, truncates existing file to zero length
     |  or creates a new file for reading and writing.
-----+--------------------------------------------------------
"a"  |  Write-only, starts at end of file if file exists,
     |  otherwise creates a new file for writing.
-----+--------------------------------------------------------
"a+" |  Read-write, starts at end of file if file exists,
     |  otherwise creates a new file for reading and
     |  writing.
-----+--------------------------------------------------------
 "b" |  Binary file mode (may appear with
     |  any of the key letters listed above).
     |  Suppresses EOL <-> CRLF conversion on Windows. And
     |  sets external encoding to ASCII-8BIT unless explicitly
     |  specified.
-----+--------------------------------------------------------
 "t" |  Text file mode (may appear with
     |  any of the key letters listed above except "b").

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

Direct Known Subclasses

File

Constant Summary

SEEK_SET =
INT2FIX(SEEK_SET)
SEEK_CUR =
INT2FIX(SEEK_CUR)
SEEK_END =
INT2FIX(SEEK_END)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from Enumerable

#all?, #any?, #chunk, #collect, #collect_concat, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #find, #find_all, #find_index, #first, #flat_map, #grep, #group_by, #include?, #inject, #map, #max, #max_by, #member?, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reject, #reverse_each, #select, #slice_before, #sort, #sort_by, #take, #take_while, #to_a, #zip

Constructor Details

- (IO) new(fd[, mode][, opt])

Returns a new IO object (a stream) for the given IO object or integer file descriptor and mode string. See also IO.sysopen and IO.for_fd.

Parameters

fd

numeric file descriptor

mode

file mode. a string or an integer

opt

hash for specifying mode by name.

Mode

When mode is an integer it must be combination of the modes defined in File::Constants.

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

  • "fmode",

  • "fmode:extern",

  • "fmode:extern:intern".

extern is the external encoding name for the IO. intern is the internal encoding. fmode must be combination of the directives. See the description of class IO for a description of the directives.

When the mode of original IO is read only, the mode cannot be changed to be writable. Similarly, the mode cannot be changed from write only to readable. If such a wrong change is directed, timing where the error actually occurs is different according to the platform.

Options

opt can have the following keys

:mode

same as mode parameter

:external_encoding

external encoding for the IO. "-" is a synonym for the default external encoding.

:internal_encoding

internal encoding for the IO. "-" is a synonym for the default internal encoding. If the value is nil no conversion occurs.

:encoding

specifies external and internal encodings as "extern:intern".

:textmode

If the value is truth value, same as "t" in argument mode.

:binmode

If the value is truth value, same as "b" in argument mode.

:autoclose

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

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

Example1

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

produces:

Hello
World

Example2

require 'fcntl'

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

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

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



# File 'io.c'

/*
 *  call-seq:
 *     IO.new(fd [, mode] [, opt])   -> io
 *
 *  Returns a new <code>IO</code> object (a stream) for the given
 *  <code>IO</code> object or integer file descriptor and mode
 *  string. See also <code>IO.sysopen</code> and
 *  <code>IO.for_fd</code>.
 *
 *  === Parameters
 *  fd:: numeric file descriptor
 *  mode:: file mode. a string or an integer
 *  opt:: hash for specifying mode by name.
 *
 *  ==== Mode
 *  When <code>mode</code> is an integer it must be combination of
 *  the modes defined in <code>File::Constants</code>.
 *
 *  When <code>mode</code> is a string it must be in one of the
 *  following forms:
 *  - "fmode",
 *  - "fmode:extern",
 *  - "fmode:extern:intern".
 *  <code>extern</code> is the external encoding name for the IO.
 *  <code>intern</code> is the internal encoding.
 *  <code>fmode</code> must be combination of the directives. See
 *  the description of class +IO+ for a description of the directives.
 *
 *  When the mode of original IO is read only, the mode cannot be changed to
 *  be writable.  Similarly, the mode cannot be changed from write only to
 *  readable.
 *  If such a wrong change is directed, timing where the error actually occurs
 *  is different according to the platform.
 *
 *  ==== Options
 *  <code>opt</code> can have the following keys
 *  :mode ::
 *    same as <code>mode</code> parameter
 *  :external_encoding ::
 *    external encoding for the IO. "-" is a
 *    synonym for the default external encoding.
 *  :internal_encoding ::
 *    internal encoding for the IO.
 *    "-" is a synonym for the default internal encoding.
 *    If the value is nil no conversion occurs.
 *  :encoding ::
 *    specifies external and internal encodings as "extern:intern".
 *  :textmode ::
 *    If the value is truth value, same as "t" in argument <code>mode</code>.
 *  :binmode ::
 *    If the value is truth value, same as "b" in argument <code>mode</code>.
 *  :autoclose ::
 *    If the value is +false+, the _fd_ will be kept open after this
 *    +IO+ instance gets finalized.
 *
 *  Also <code>opt</code> can have same keys in <code>String#encode</code> for
 *  controlling conversion between the external encoding and the internal encoding.
 *
 *  === Example1
 *
 *     fd = IO.sysopen("/dev/tty", "w")
 *     a = IO.new(fd,"w")
 *     $stderr.puts "Hello"
 *     a.puts "World"
 *
 *  <em>produces:</em>
 *
 *     Hello
 *     World
 *
 *  === Example2
 *
 *     require 'fcntl'
 *
 *     fd = STDERR.fcntl(Fcntl::F_DUPFD)
 *     io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
 *     io.puts "Hello, World!"
 *
 *     fd = STDERR.fcntl(Fcntl::F_DUPFD)
 *     io = IO.new(fd, mode: 'w', cr_newline: true, external_encoding: Encoding::UTF_16LE)
 *     io.puts "Hello, World!"
 *
 *  both of above print "Hello, World!" in UTF-16LE to standard error output with
 *  converting EOL generated by <code>puts</code> to CR.
 */

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

    rb_secure(4);

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

    fd = NUM2INT(fnum);
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    oflags = fcntl(fd, F_GETFL);
    if (oflags == -1) rb_sys_fail(0);
#else
    if (fstat(fd, &st) == -1) rb_sys_fail(0);
#endif
    UPDATE_MAXFD(fd);
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    ofmode = rb_io_oflags_fmode(oflags);
    if (NIL_P(vmode)) {
    fmode = ofmode;
    }
    else if ((~ofmode & fmode) & FMODE_READWRITE) {
    VALUE error = INT2FIX(EINVAL);
    rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
    }
#endif
    if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
    fmode |= FMODE_PREP;
    }
    MakeOpenFile(io, fp);
    fp->fd = fd;
    fp->mode = fmode;
    fp->encs = convconfig;
    clear_codeconv(fp);
    io_check_tty(fp);
    if (fileno(stdin) == fd)
    fp->stdio_file = stdin;
    else if (fileno(stdout) == fd)
    fp->stdio_file = stdout;
    else if (fileno(stderr) == fd)
    fp->stdio_file = stderr;

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

Class Method Details

+ (String) binread(name, [length [, offset]])

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     IO.binread(name, [length [, offset]] )   -> string
 *
 *  Opens the file, optionally seeks to the given <i>offset</i>, then returns
 *  <i>length</i> bytes (defaulting to the rest of the file).
 *  <code>binread</code> ensures the file is closed before returning.
 *  The open mode would be "rb:ASCII-8BIT".
 *
 *     IO.binread("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
 *     IO.binread("testfile", 20)       #=> "This is line one\nThi"
 *     IO.binread("testfile", 20, 10)   #=> "ne one\nThis is line "
 */

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

    rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
    FilePathValue(argv[0]);
    arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
    if (NIL_P(arg.io)) return Qnil;
    arg.argv = argv+1;
    arg.argc = (argc > 1) ? 1 : 0;
    if (!NIL_P(offset)) {
    rb_io_seek(arg.io, offset, SEEK_SET);
    }
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}

+ (Object) copy_stream(src, dst) + (Object) copy_stream(src, dst, copy_length) + (Object) copy_stream(src, dst, copy_length, src_offset)

IO.copy_stream copies src to dst. src and dst is either a filename or an IO.

This method returns the number of bytes copied.

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

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

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

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



# File 'io.c'

/*
 *  call-seq:
 *     IO.copy_stream(src, dst)
 *     IO.copy_stream(src, dst, copy_length)
 *     IO.copy_stream(src, dst, copy_length, src_offset)
 *
 *  IO.copy_stream copies <i>src</i> to <i>dst</i>.
 *  <i>src</i> and <i>dst</i> is either a filename or an IO.
 *
 *  This method returns the number of bytes copied.
 *
 *  If optional arguments are not given,
 *  the start position of the copy is
 *  the beginning of the filename or
 *  the current file offset of the IO.
 *  The end position of the copy is the end of file.
 *
 *  If <i>copy_length</i> is given,
 *  No more than <i>copy_length</i> bytes are copied.
 *
 *  If <i>src_offset</i> is given,
 *  it specifies the start position of the copy.
 *
 *  When <i>src_offset</i> is specified and
 *  <i>src</i> is an IO,
 *  IO.copy_stream doesn't move the current file offset.
 *
 */
static VALUE
rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
{
    VALUE src, dst, length, src_offset;
    struct copy_stream_struct st;

    MEMZERO(&st, struct copy_stream_struct, 1);

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

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

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

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

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

    return OFFT2NUM(st.total);
}

+ (IO) for_fd(fd, mode[, opt])

Synonym for IO.new.

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     IO.for_fd(fd, mode [, opt])    -> io
 *
 *  Synonym for <code>IO.new</code>.
 *
 */

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

+ (nil) foreach(name, sep = $/[, open_args]) {|line| ... } + (nil) foreach(name, limit[, open_args]) {|line| ... } + (nil) foreach(name, sep, limit[, open_args]) {|line| ... } + (Object) foreach(...)

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

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

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

produces:

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

If the last argument is a hash, it's the keyword argument to open. See IO.read for detail.

Overloads:

  • + (nil) foreach(name, sep = $/[, open_args]) {|line| ... }

    Yields:

    • (line)

    Returns:

    • (nil)
  • + (nil) foreach(name, limit[, open_args]) {|line| ... }

    Yields:

    • (line)

    Returns:

    • (nil)
  • + (nil) foreach(name, sep, limit[, open_args]) {|line| ... }

    Yields:

    • (line)

    Returns:

    • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     IO.foreach(name, sep=$/ [, open_args]) {|line| block }     -> nil
 *     IO.foreach(name, limit [, open_args]) {|line| block }      -> nil
 *     IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil
 *     IO.foreach(...)                                            -> an_enumerator
 *
 *  Executes the block for every line in the named I/O port, where lines
 *  are separated by <em>sep</em>.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     IO.foreach("testfile") {|x| print "GOT ", x }
 *
 *  <em>produces:</em>
 *
 *     GOT This is line one
 *     GOT This is line two
 *     GOT This is line three
 *     GOT And so on...
 *
 *  If the last argument is a hash, it's the keyword argument to open.
 *  See <code>IO.read</code> for detail.
 *
 */

static VALUE
rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
{
    struct foreach_arg arg;

    rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
    RETURN_ENUMERATOR(self, argc, argv);
    open_key_args(argc, argv, &arg);
    if (NIL_P(arg.io)) return Qnil;
    return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
}

+ (Object) new

:nodoc:



# File 'io.c'

/* :nodoc: */
static VALUE
rb_io_s_new(int argc, VALUE *argv, VALUE klass)
{
    if (rb_block_given_p()) {
    const char *cname = rb_class2name(klass);

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

+ (IO) open(fd, mode_string = "r"[, opt]) + (Object) open(fd, mode_string = "r"[, opt]) {|io| ... }

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

Overloads:

  • + (IO) open(fd, mode_string = "r"[, opt])

    Returns:

  • + (Object) open(fd, mode_string = "r"[, opt]) {|io| ... }

    Yields:

    • (io)

    Returns:



# File 'io.c'

/*
 *  Document-method: IO::open
 *
 *  call-seq:
 *     IO.open(fd, mode_string="r" [, opt] )               -> io
 *     IO.open(fd, mode_string="r" [, opt] ) {|io| block } -> obj
 *
 *  With no associated block, <code>open</code> is a synonym for
 *  <code>IO.new</code>. If the optional code block is given, it will
 *  be passed <i>io</i> as an argument, and the IO object will
 *  automatically be closed when the block terminates. In this instance,
 *  <code>IO.open</code> returns the value of the block.
 *
 */

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

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

    return io;
}

+ (Array) pipe + (Array) pipe(ext_enc) + (Array) pipe("ext_enc:int_enc"[, opt]) + (Array) pipe(ext_enc, int_enc[, opt])

IO.pipe(...) {|read_io, write_io| ... }

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

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

Not available on all platforms.

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

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

rd, wr = IO.pipe

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

produces:

Sending message to parent
Parent got: <Hi Dad>

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     IO.pipe                             ->  [read_io, write_io]
 *     IO.pipe(ext_enc)                    ->  [read_io, write_io]
 *     IO.pipe("ext_enc:int_enc" [, opt])  ->  [read_io, write_io]
 *     IO.pipe(ext_enc, int_enc [, opt])   ->  [read_io, write_io]
 *
 *     IO.pipe(...) {|read_io, write_io| ... }
 *
 *  Creates a pair of pipe endpoints (connected to each other) and
 *  returns them as a two-element array of <code>IO</code> objects:
 *  <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
 *
 *  If a block is given, the block is called and
 *  returns the value of the block.
 *  <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
 *  If read_io and write_io are not closed when the block exits, they are closed.
 *  i.e. closing read_io and/or write_io doesn't cause an error.
 *
 *  Not available on all platforms.
 *
 *  If an encoding (encoding name or encoding object) is specified as an optional argument,
 *  read string from pipe is tagged with the encoding specified.
 *  If the argument is a colon separated two encoding names "A:B",
 *  the read string is converted from encoding A (external encoding)
 *  to encoding B (internal encoding), then tagged with B.
 *  If two optional arguments are specified, those must be
 *  encoding objects or encoding names,
 *  and the first one is the external encoding,
 *  and the second one is the internal encoding.
 *  If the external encoding and the internal encoding is specified,
 *  optional hash argument specify the conversion option.
 *
 *  In the example below, the two processes close the ends of the pipe
 *  that they are not using. This is not just a cosmetic nicety. The
 *  read end of a pipe will not generate an end of file condition if
 *  there are any writers with the pipe still open. In the case of the
 *  parent process, the <code>rd.read</code> will never return if it
 *  does not first issue a <code>wr.close</code>.
 *
 *     rd, wr = IO.pipe
 *
 *     if fork
 *       wr.close
 *       puts "Parent got: <#{rd.read}>"
 *       rd.close
 *       Process.wait
 *     else
 *       rd.close
 *       puts "Sending message to parent"
 *       wr.write "Hi Dad"
 *       wr.close
 *     end
 *
 *  <em>produces:</em>
 *
 *     Sending message to parent
 *     Parent got: <Hi Dad>
 */

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

    opt = pop_last_hash(&argc, argv);
    rb_scan_args(argc, argv, "02", &v1, &v2);
    if (rb_pipe(pipes) == -1)
        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);
    io_encoding_set(fptr, v1, v2, opt);
    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);
    fptr->mode |= fmode;
    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;
}

+ (IO) popen(cmd, mode = "r"[, opt]) + (Object) popen(cmd, mode = "r"[, opt]) {|io| ... }

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

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

cmd is a string or an array as follows.

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

If cmd is a String "-'', then a new instance of Ruby is started as the subprocess.

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

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

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

# merge standard output and standard error using
# spawn option.  See the document of Kernel.spawn.
IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
  ls_result_with_error = ls_io.read
}

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

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

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

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

produces:

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

Overloads:

  • + (IO) popen(cmd, mode = "r"[, opt])

    Returns:

  • + (Object) popen(cmd, mode = "r"[, opt]) {|io| ... }

    Yields:

    • (io)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     IO.popen(cmd, mode="r" [, opt])               -> io
 *     IO.popen(cmd, mode="r" [, opt]) {|io| block } -> obj
 *
 *  Runs the specified command as a subprocess; the subprocess's
 *  standard input and output will be connected to the returned
 *  <code>IO</code> object.
 *
 *  The PID of the started process can be obtained by IO#pid method.
 *
 *  _cmd_ is a string or an array as follows.
 *
 *    cmd:
 *      "-"                                      : fork
 *      commandline                              : command line string which is passed to a shell
 *      [env, cmdname, arg1, ..., opts]          : command name and zero or more arguments (no shell)
 *      [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
 *    (env and opts are optional.)
 *
 *  If _cmd_ is a +String+ ``<code>-</code>'',
 *  then a new instance of Ruby is started as the subprocess.
 *
 *  If <i>cmd</i> is an +Array+ of +String+,
 *  then it will be used as the subprocess's +argv+ bypassing a shell.
 *  The array can contains a hash at first for environments and
 *  a hash at last for options similar to <code>spawn</code>.
 *
 *  The default mode for the new file object is ``r'',
 *  but <i>mode</i> may be set to any of the modes listed in the description for class IO.
 *  The last argument <i>opt</i> qualifies <i>mode</i>.
 *
 *    # set IO encoding
 *    IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
 *      euc_jp_string = nkf_io.read
 *    }
 *
 *    # merge standard output and standard error using
 *    # spawn option.  See the document of Kernel.spawn.
 *    IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
 *      ls_result_with_error = ls_io.read
 *    }
 *
 *  Raises exceptions which <code>IO.pipe</code> and
 *  <code>Kernel.spawn</code> raise.
 *
 *  If a block is given, Ruby will run the command as a child connected
 *  to Ruby with a pipe. Ruby's end of the pipe will be passed as a
 *  parameter to the block.
 *  At the end of block, Ruby close the pipe and sets <code>$?</code>.
 *  In this case <code>IO.popen</code> returns
 *  the value of the block.
 *
 *  If a block is given with a _cmd_ of ``<code>-</code>'',
 *  the block will be run in two separate processes: once in the parent,
 *  and once in a child. The parent process will be passed the pipe
 *  object as a parameter to the block, the child version of the block
 *  will be passed <code>nil</code>, and the child's standard in and
 *  standard out will be connected to the parent through the pipe. Not
 *  available on all platforms.
 *
 *     f = IO.popen("uname")
 *     p f.readlines
 *     f.close
 *     puts "Parent is #{Process.pid}"
 *     IO.popen("date") { |f| puts f.gets }
 *     IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
 *     p $?
 *     IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
 *       f.puts "bar"; f.close_write; puts f.gets
 *     }
 *
 *  <em>produces:</em>
 *
 *     ["Linux\n"]
 *     Parent is 21346
 *     Thu Jan 15 22:41:19 JST 2009
 *     21346 is here, f is #<IO:fd 3>
 *     21352 is here, f is nil
 *     #<Process::Status: pid 21352 exit 0>
 *     <foo>bar;zot;
 */

static VALUE
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
{
    const char *modestr;
    VALUE pname, pmode, port, tmp, opt;
    int oflags, fmode;
    convconfig_t convconfig;

    opt = pop_last_hash(&argc, argv);
    rb_scan_args(argc, argv, "11", &pname, &pmode);

    rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
    modestr = rb_io_oflags_modestr(oflags);

    tmp = rb_check_array_type(pname);
    if (!NIL_P(tmp)) {
    long len = RARRAY_LEN(tmp);
#if SIZEOF_LONG > SIZEOF_INT
    if (len > INT_MAX) {
        rb_raise(rb_eArgError, "too many arguments");
    }
#endif
    tmp = rb_ary_dup(tmp);
    RBASIC(tmp)->klass = 0;
    port = pipe_open_v((int)len, RARRAY_PTR(tmp), modestr, fmode, &convconfig);
    rb_ary_clear(tmp);
    }
    else {
    SafeStringValue(pname);
    port = pipe_open_s(pname, modestr, fmode, &convconfig);
    }
    if (NIL_P(port)) {
    /* child */
    if (rb_block_given_p()) {
        rb_yield(Qnil);
            rb_io_flush(rb_stdout);
            rb_io_flush(rb_stderr);
        _exit(0);
    }
    return Qnil;
    }
    RBASIC(port)->klass = klass;
    if (rb_block_given_p()) {
    return rb_ensure(rb_yield, port, io_close, port);
    }
    return port;
}

+ (String) read(name, [length [, offset]]) + (String) read(name, [length [, offset]], open_args)

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

If the last argument is a hash, it specifies option for internal open(). The key would be the following. open_args: is exclusive to others.

encoding: string or encoding

 specifies encoding of the read string.  encoding will be ignored
 if length is specified.

mode: string

 specifies mode argument for open().  it should start with "r"
 otherwise it would cause error.

open_args: array of strings

 specifies arguments for open() as an array.

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

Overloads:

  • + (String) read(name, [length [, offset]])

    Returns:

  • + (String) read(name, [length [, offset]], open_args)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     IO.read(name, [length [, offset]] )   -> string
 *     IO.read(name, [length [, offset]], open_args)   -> string
 *
 *  Opens the file, optionally seeks to the given <i>offset</i>, then returns
 *  <i>length</i> bytes (defaulting to the rest of the file).
 *  <code>read</code> ensures the file is closed before returning.
 *
 *  If the last argument is a hash, it specifies option for internal
 *  open().  The key would be the following.  open_args: is exclusive
 *  to others.
 *
 *   encoding: string or encoding
 *
 *    specifies encoding of the read string.  encoding will be ignored
 *    if length is specified.
 *
 *   mode: string
 *
 *    specifies mode argument for open().  it should start with "r"
 *    otherwise it would cause error.
 *
 *   open_args: array of strings
 *
 *    specifies arguments for open() as an array.
 *
 *     IO.read("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
 *     IO.read("testfile", 20)       #=> "This is line one\nThi"
 *     IO.read("testfile", 20, 10)   #=> "ne one\nThis is line "
 */

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

    rb_scan_args(argc, argv, "13", NULL, NULL, &offset, NULL);
    open_key_args(argc, argv, &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);
}

+ (Array) readlines(name, sep = $/[, open_args]) + (Array) readlines(name, limit[, open_args]) + (Array) readlines(name, sep, limit[, open_args])

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

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

If the last argument is a hash, it's the keyword argument to open. See IO.read for detail.

Overloads:

  • + (Array) readlines(name, sep = $/[, open_args])

    Returns:

  • + (Array) readlines(name, limit[, open_args])

    Returns:

  • + (Array) readlines(name, sep, limit[, open_args])

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     IO.readlines(name, sep=$/ [, open_args])     -> array
 *     IO.readlines(name, limit [, open_args])      -> array
 *     IO.readlines(name, sep, limit [, open_args]) -> array
 *
 *  Reads the entire file specified by <i>name</i> as individual
 *  lines, and returns those lines in an array. Lines are separated by
 *  <i>sep</i>.
 *
 *     a = IO.readlines("testfile")
 *     a[0]   #=> "This is line one\n"
 *
 *  If the last argument is a hash, it's the keyword argument to open.
 *  See <code>IO.read</code> for detail.
 *
 */

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

    rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
    open_key_args(argc, argv, &arg);
    if (NIL_P(arg.io)) return Qnil;
    return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
}

+ (Object) select(read_array)

[, error_array

[, timeout]]] )-> array  or  nil

See Kernel#select.



# File 'io.c'

/*
 *  call-seq:
 *     IO.select(read_array
 *               [, write_array
 *               [, error_array
 *               [, timeout]]] )-> array  or  nil
 *
 *  See <code>Kernel#select</code>.
 */

static VALUE
rb_f_select(int argc, VALUE *argv, VALUE obj)
{
    VALUE timeout;
    struct select_args args;
    struct timeval timerec;
    int i;

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

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

#ifdef HAVE_RB_FD_INIT
    return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
#else
    return select_internal(args.read, args.write, args.except,
               args.timeout, args.fdsets);
#endif

}

+ (Fixnum) sysopen(path, [mode, [perm]])

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     IO.sysopen(path, [mode, [perm]])  -> fixnum
 *
 *  Opens the given path, returning the underlying file descriptor as a
 *  <code>Fixnum</code>.
 *
 *     IO.sysopen("testfile")   #=> 3
 *
 */

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

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

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

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

+ (IO?) try_convert(obj)

Try to convert obj into an IO, using to_io method. Returns converted IO or nil if obj cannot be converted for any reason.

IO.try_convert(STDOUT)     #=> STDOUT
IO.try_convert("STDOUT")   #=> nil

require 'zlib'
f = open("/tmp/zz.gz")       #=> #<File:/tmp/zz.gz>
z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
IO.try_convert(z)            #=> #<File:/tmp/zz.gz>

Returns:

  • (IO, nil)


# File 'io.c'

/*
 *  call-seq:
 *     IO.try_convert(obj)  ->  io or nil
 *
 *  Try to convert <i>obj</i> into an IO, using to_io method.
 *  Returns converted IO or nil if <i>obj</i> cannot be converted
 *  for any reason.
 *
 *     IO.try_convert(STDOUT)     #=> STDOUT
 *     IO.try_convert("STDOUT")   #=> nil
 *
 *     require 'zlib'
 *     f = open("/tmp/zz.gz")       #=> #<File:/tmp/zz.gz>
 *     z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
 *     IO.try_convert(z)            #=> #<File:/tmp/zz.gz>
 *
 */
static VALUE
rb_io_s_try_convert(VALUE dummy, VALUE io)
{
    return rb_io_check_io(io);
}

Instance Method Details

- (IO) <<(obj)

String Output---Writes obj to ios. obj will be converted to a string using to_s.

$stdout << "Hello " << "world!\n"

produces:

Hello world!

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios << obj     -> ios
 *
 *  String Output---Writes <i>obj</i> to <em>ios</em>.
 *  <i>obj</i> will be converted to a string using
 *  <code>to_s</code>.
 *
 *     $stdout << "Hello " << "world!\n"
 *
 *  <em>produces:</em>
 *
 *     Hello world!
 */


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

- (Boolean) autoclose=(bool)

Sets auto-close flag.

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

f = open("/dev/null")
IO.for_fd(f.fileno).autoclose = true
# ...
f.gets # won't cause IOError

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     io.autoclose = bool    -> true or false
 *
 *  Sets auto-close flag.
 *
 *     f = open("/dev/null")
 *     IO.for_fd(f.fileno)
 *     # ...
 *     f.gets # may cause IOError
 *
 *     f = open("/dev/null")
 *     IO.for_fd(f.fileno).autoclose = true
 *     # ...
 *     f.gets # won't cause IOError
 */

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

- (Boolean) autoclose?

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

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.autoclose?   -> true or false
 *
 *  Returns +true+ if the underlying file descriptor of _ios_ will be
 *  closed automatically at its finalization, otherwise +false+.
 */

static VALUE
rb_io_autoclose_p(VALUE io)
{
    rb_io_t *fptr;
    rb_secure(4);
    GetOpenFile(io, fptr);
    return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
}

- (IO) binmode

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

  • newline conversion disabled

  • encoding conversion disabled

  • content is treated as ASCII-8BIT

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.binmode    -> ios
 *
 *  Puts <em>ios</em> into binary mode.
 *  Once a stream is in binary mode, it cannot be reset to nonbinary mode.
 *
 *  - newline conversion disabled
 *  - encoding conversion disabled
 *  - content is treated as ASCII-8BIT
 *
 */

static VALUE
rb_io_binmode_m(VALUE io)
{
    VALUE write_io;

    rb_io_ascii8bit_binmode(io);

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

- (Boolean) binmode?

Returns true if ios is binmode.

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.binmode?    -> true or false
 *
 *  Returns <code>true</code> if <em>ios</em> is binmode.
 */
static VALUE
rb_io_binmode_p(VALUE io)
{
    rb_io_t *fptr;
    GetOpenFile(io, fptr);
    return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
}

- (IO) bytes {|byte| ... } - (Object) bytes

ios.each_byte {|byte| block } -> ios

ios.each_byte                  -> an_enumerator

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

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

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

Overloads:

  • - (IO) bytes {|byte| ... }

    Yields:

    • (byte)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.bytes {|byte| block }      -> ios
 *     ios.bytes                      -> an_enumerator
 *
 *     ios.each_byte {|byte| block }  -> ios
 *     ios.each_byte                  -> an_enumerator
 *
 *  Calls the given block once for each byte (0..255) in <em>ios</em>,
 *  passing the byte as an argument. The stream must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     f = File.new("testfile")
 *     checksum = 0
 *     f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
 *     checksum                           #=> 12
 */

static VALUE
rb_io_each_byte(VALUE io)
{
    rb_io_t *fptr;
    char *p, *e;

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

    for (;;) {
    p = fptr->rbuf+fptr->rbuf_off;
    e = p + fptr->rbuf_len;
    while (p < e) {
        fptr->rbuf_off++;
        fptr->rbuf_len--;
        rb_yield(INT2FIX(*p & 0xff));
        p++;
        errno = 0;
    }
    rb_io_check_byte_readable(fptr);
    READ_CHECK(fptr);
    if (io_fillbuf(fptr) < 0) {
        break;
    }
    }
    return io;
}

- (IO) chars {|c| ... } - (Object) chars

ios.each_char {|c| block } -> ios

ios.each_char               -> an_enumerator

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

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

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

Overloads:

  • - (IO) chars {|c| ... }

    Yields:

    • (c)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.chars {|c| block }      -> ios
 *     ios.chars                   -> an_enumerator
 *
 *     ios.each_char {|c| block }  -> ios
 *     ios.each_char               -> an_enumerator
 *
 *  Calls the given block once for each character in <em>ios</em>,
 *  passing the character as an argument. The stream must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     f = File.new("testfile")
 *     f.each_char {|c| print c, ' ' }   #=> #<File:testfile>
 */

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

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

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

- (nil) close

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

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

Returns:

  • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.close   -> nil
 *
 *  Closes <em>ios</em> and flushes any pending writes to the operating
 *  system. The stream is unavailable for any further data operations;
 *  an <code>IOError</code> is raised if such an attempt is made. I/O
 *  streams are automatically closed when they are claimed by the
 *  garbage collector.
 *
 *  If <em>ios</em> is opened by <code>IO.popen</code>,
 *  <code>close</code> sets <code>$?</code>.
 */

static VALUE
rb_io_close_m(VALUE io)
{
    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
    rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    rb_io_check_closed(RFILE(io)->fptr);
    rb_io_close(io);
    return Qnil;
}

- (Boolean) close_on_exec=(bool)

Sets a close-on-exec flag.

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

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.close_on_exec = bool    -> true or false
 *
 *  Sets a close-on-exec flag.
 *
 *     f = open("/dev/null")
 *     f.close_on_exec = true
 *     system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
 *     f.closed?                #=> false
 */

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

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

- (Boolean) close_on_exec?

Returns true if ios will be closed on exec.

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

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.close_on_exec?   -> true or false
 *
 *  Returns <code>true</code> if <em>ios</em> will be closed on exec.
 *
 *     f = open("/dev/null")
 *     f.close_on_exec?                 #=> false
 *     f.close_on_exec = true
 *     f.close_on_exec?                 #=> true
 *     f.close_on_exec = false
 *     f.close_on_exec?                 #=> false
 */

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

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

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

- (nil) close_read

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

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

produces:

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

Returns:

  • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.close_read    -> nil
 *
 *  Closes the read end of a duplex I/O stream (i.e., one that contains
 *  both a read and a write stream, such as a pipe). Will raise an
 *  <code>IOError</code> if the stream is not duplexed.
 *
 *     f = IO.popen("/bin/sh","r+")
 *     f.close_read
 *     f.readlines
 *
 *  <em>produces:</em>
 *
 *     prog.rb:3:in `readlines': not opened for reading (IOError)
 *      from prog.rb:3
 */

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

    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
    rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    GetOpenFile(io, fptr);
    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;
        rb_io_fptr_cleanup(fptr, FALSE);
    GetOpenFile(write_io, wfptr);
        RFILE(io)->fptr = wfptr;
        RFILE(write_io)->fptr = NULL;
        rb_io_fptr_finalize(fptr);
        return Qnil;
    }

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

- (nil) close_write

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

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

produces:

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

Returns:

  • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.close_write   -> nil
 *
 *  Closes the write end of a duplex I/O stream (i.e., one that contains
 *  both a read and a write stream, such as a pipe). Will raise an
 *  <code>IOError</code> if the stream is not duplexed.
 *
 *     f = IO.popen("/bin/sh","r+")
 *     f.close_write
 *     f.print "nowhere"
 *
 *  <em>produces:</em>
 *
 *     prog.rb:3:in `write': not opened for writing (IOError)
 *      from prog.rb:3:in `print'
 *      from prog.rb:3
 */

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

    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
    rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    write_io = GetWriteIO(io);
    GetOpenFile(write_io, fptr);
    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_READABLE) {
    rb_raise(rb_eIOError, "closing non-duplex IO for writing");
    }

    rb_io_close(write_io);
    if (io != write_io) {
    GetOpenFile(io, fptr);
    fptr->tied_io_for_writing = 0;
    fptr->mode &= ~FMODE_DUPLEX;
    }
    return Qnil;
}

- (Boolean) closed?

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

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

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.closed?    -> true or false
 *
 *  Returns <code>true</code> if <em>ios</em> is completely closed (for
 *  duplex streams, both reader and writer), <code>false</code>
 *  otherwise.
 *
 *     f = File.new("testfile")
 *     f.close         #=> nil
 *     f.closed?       #=> true
 *     f = IO.popen("/bin/sh","r+")
 *     f.close_write   #=> nil
 *     f.closed?       #=> false
 *     f.close_read    #=> nil
 *     f.closed?       #=> true
 */


static VALUE
rb_io_closed(VALUE io)
{
    rb_io_t *fptr;
    VALUE write_io;
    rb_io_t *write_fptr;

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

    fptr = RFILE(io)->fptr;
    rb_io_check_initialized(fptr);
    return 0 <= fptr->fd ? Qfalse : Qtrue;
}

- (IO) each_codepoint {|c| ... } - (IO) codepoints {|c| ... } - (Object) each_codepoint - (Object) codepoints

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

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

Overloads:

  • - (IO) each_codepoint {|c| ... }

    Yields:

    • (c)

    Returns:

  • - (IO) codepoints {|c| ... }

    Yields:

    • (c)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.each_codepoint {|c| block }  -> ios
 *     ios.codepoints     {|c| block }  -> ios
 *     ios.each_codepoint               -> an_enumerator
 *     ios.codepoints                   -> an_enumerator
 *
 *  Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
 *  passing the codepoint as an argument. The stream must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 */

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

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

    READ_CHECK(fptr);
    if (NEED_READCONV(fptr)) {
    for (;;) {
        make_readconv(fptr, 0);
        for (;;) {
        if (fptr->cbuf_len) {
            if (fptr->encs.enc)
            r = rb_enc_precise_mbclen(fptr->cbuf+fptr->cbuf_off,
                          fptr->cbuf+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);
            /* ignore an incomplete character before EOF */
            return io;
        }
        }
        if (MBCLEN_INVALID_P(r)) {
        rb_raise(rb_eArgError, "invalid byte sequence in %s",
             rb_enc_name(fptr->encs.enc));
        }
        n = MBCLEN_CHARFOUND_LEN(r);
        if (fptr->encs.enc) {
        c = rb_enc_codepoint(fptr->cbuf+fptr->cbuf_off,
                     fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
                     fptr->encs.enc);
        }
        else {
        c = (unsigned char)fptr->cbuf[fptr->cbuf_off];
        }
        fptr->cbuf_off += n;
        fptr->cbuf_len -= n;
        rb_yield(UINT2NUM(c));
    }
    }
    enc = io_input_encoding(fptr);
    for (;;) {
    if (io_fillbuf(fptr) < 0) {
        return io;
    }
    r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off,
                  fptr->rbuf+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+fptr->rbuf_off,
                 fptr->rbuf+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)) {
        rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
    }
    else {
        continue;
    }
    }
    return io;
}

- (IO) each(sep = $/) {|line| ... } - (IO) each(limit) {|line| ... } - (IO) each(sep, limit) {|line| ... } - (Object) each(...)

ios.each_line(sep=$/) {|line| block } -> ios

ios.each_line(limit) {|line| block }     -> ios
ios.each_line(sep,limit) {|line| block } -> ios
ios.each_line(...)                       -> an_enumerator

ios.lines(sep=$/) {|line| block }        -> ios
ios.lines(limit) {|line| block }         -> ios
ios.lines(sep,limit) {|line| block }     -> ios
ios.lines(...)                           -> an_enumerator

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

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

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

produces:

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

Overloads:

  • - (IO) each(sep = $/) {|line| ... }

    Yields:

    • (line)

    Returns:

  • - (IO) each(limit) {|line| ... }

    Yields:

    • (line)

    Returns:

  • - (IO) each(sep, limit) {|line| ... }

    Yields:

    • (line)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.each(sep=$/) {|line| block }         -> ios
 *     ios.each(limit) {|line| block }          -> ios
 *     ios.each(sep,limit) {|line| block }      -> ios
 *     ios.each(...)                            -> an_enumerator
 *
 *     ios.each_line(sep=$/) {|line| block }    -> ios
 *     ios.each_line(limit) {|line| block }     -> ios
 *     ios.each_line(sep,limit) {|line| block } -> ios
 *     ios.each_line(...)                       -> an_enumerator
 *
 *     ios.lines(sep=$/) {|line| block }        -> ios
 *     ios.lines(limit) {|line| block }         -> ios
 *     ios.lines(sep,limit) {|line| block }     -> ios
 *     ios.lines(...)                           -> an_enumerator
 *
 *  Executes the block for every line in <em>ios</em>, where lines are
 *  separated by <i>sep</i>. <em>ios</em> must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     f = File.new("testfile")
 *     f.each {|line| puts "#{f.lineno}: #{line}" }
 *
 *  <em>produces:</em>
 *
 *     1: This is line one
 *     2: This is line two
 *     3: This is line three
 *     4: And so on...
 */

static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
    VALUE str, rs;
    long limit;

    RETURN_ENUMERATOR(io, argc, argv);
    prepare_getline_args(argc, argv, &rs, &limit, io);
    while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
    rb_yield(str);
    }
    return io;
}

- (IO) bytes {|byte| ... } - (Object) bytes

ios.each_byte {|byte| block } -> ios

ios.each_byte                  -> an_enumerator

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

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

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

Overloads:

  • - (IO) bytes {|byte| ... }

    Yields:

    • (byte)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.bytes {|byte| block }      -> ios
 *     ios.bytes                      -> an_enumerator
 *
 *     ios.each_byte {|byte| block }  -> ios
 *     ios.each_byte                  -> an_enumerator
 *
 *  Calls the given block once for each byte (0..255) in <em>ios</em>,
 *  passing the byte as an argument. The stream must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     f = File.new("testfile")
 *     checksum = 0
 *     f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
 *     checksum                           #=> 12
 */

static VALUE
rb_io_each_byte(VALUE io)
{
    rb_io_t *fptr;
    char *p, *e;

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

    for (;;) {
    p = fptr->rbuf+fptr->rbuf_off;
    e = p + fptr->rbuf_len;
    while (p < e) {
        fptr->rbuf_off++;
        fptr->rbuf_len--;
        rb_yield(INT2FIX(*p & 0xff));
        p++;
        errno = 0;
    }
    rb_io_check_byte_readable(fptr);
    READ_CHECK(fptr);
    if (io_fillbuf(fptr) < 0) {
        break;
    }
    }
    return io;
}

- (IO) chars {|c| ... } - (Object) chars

ios.each_char {|c| block } -> ios

ios.each_char               -> an_enumerator

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

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

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

Overloads:

  • - (IO) chars {|c| ... }

    Yields:

    • (c)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.chars {|c| block }      -> ios
 *     ios.chars                   -> an_enumerator
 *
 *     ios.each_char {|c| block }  -> ios
 *     ios.each_char               -> an_enumerator
 *
 *  Calls the given block once for each character in <em>ios</em>,
 *  passing the character as an argument. The stream must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     f = File.new("testfile")
 *     f.each_char {|c| print c, ' ' }   #=> #<File:testfile>
 */

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

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

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

- (IO) each_codepoint {|c| ... } - (IO) codepoints {|c| ... } - (Object) each_codepoint - (Object) codepoints

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

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

Overloads:

  • - (IO) each_codepoint {|c| ... }

    Yields:

    • (c)

    Returns:

  • - (IO) codepoints {|c| ... }

    Yields:

    • (c)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.each_codepoint {|c| block }  -> ios
 *     ios.codepoints     {|c| block }  -> ios
 *     ios.each_codepoint               -> an_enumerator
 *     ios.codepoints                   -> an_enumerator
 *
 *  Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
 *  passing the codepoint as an argument. The stream must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 */

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

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

    READ_CHECK(fptr);
    if (NEED_READCONV(fptr)) {
    for (;;) {
        make_readconv(fptr, 0);
        for (;;) {
        if (fptr->cbuf_len) {
            if (fptr->encs.enc)
            r = rb_enc_precise_mbclen(fptr->cbuf+fptr->cbuf_off,
                          fptr->cbuf+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);
            /* ignore an incomplete character before EOF */
            return io;
        }
        }
        if (MBCLEN_INVALID_P(r)) {
        rb_raise(rb_eArgError, "invalid byte sequence in %s",
             rb_enc_name(fptr->encs.enc));
        }
        n = MBCLEN_CHARFOUND_LEN(r);
        if (fptr->encs.enc) {
        c = rb_enc_codepoint(fptr->cbuf+fptr->cbuf_off,
                     fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
                     fptr->encs.enc);
        }
        else {
        c = (unsigned char)fptr->cbuf[fptr->cbuf_off];
        }
        fptr->cbuf_off += n;
        fptr->cbuf_len -= n;
        rb_yield(UINT2NUM(c));
    }
    }
    enc = io_input_encoding(fptr);
    for (;;) {
    if (io_fillbuf(fptr) < 0) {
        return io;
    }
    r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off,
                  fptr->rbuf+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+fptr->rbuf_off,
                 fptr->rbuf+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)) {
        rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
    }
    else {
        continue;
    }
    }
    return io;
}

- (IO) each(sep = $/) {|line| ... } - (IO) each(limit) {|line| ... } - (IO) each(sep, limit) {|line| ... } - (Object) each(...)

ios.each_line(sep=$/) {|line| block } -> ios

ios.each_line(limit) {|line| block }     -> ios
ios.each_line(sep,limit) {|line| block } -> ios
ios.each_line(...)                       -> an_enumerator

ios.lines(sep=$/) {|line| block }        -> ios
ios.lines(limit) {|line| block }         -> ios
ios.lines(sep,limit) {|line| block }     -> ios
ios.lines(...)                           -> an_enumerator

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

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

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

produces:

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

Overloads:

  • - (IO) each(sep = $/) {|line| ... }

    Yields:

    • (line)

    Returns:

  • - (IO) each(limit) {|line| ... }

    Yields:

    • (line)

    Returns:

  • - (IO) each(sep, limit) {|line| ... }

    Yields:

    • (line)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.each(sep=$/) {|line| block }         -> ios
 *     ios.each(limit) {|line| block }          -> ios
 *     ios.each(sep,limit) {|line| block }      -> ios
 *     ios.each(...)                            -> an_enumerator
 *
 *     ios.each_line(sep=$/) {|line| block }    -> ios
 *     ios.each_line(limit) {|line| block }     -> ios
 *     ios.each_line(sep,limit) {|line| block } -> ios
 *     ios.each_line(...)                       -> an_enumerator
 *
 *     ios.lines(sep=$/) {|line| block }        -> ios
 *     ios.lines(limit) {|line| block }         -> ios
 *     ios.lines(sep,limit) {|line| block }     -> ios
 *     ios.lines(...)                           -> an_enumerator
 *
 *  Executes the block for every line in <em>ios</em>, where lines are
 *  separated by <i>sep</i>. <em>ios</em> must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     f = File.new("testfile")
 *     f.each {|line| puts "#{f.lineno}: #{line}" }
 *
 *  <em>produces:</em>
 *
 *     1: This is line one
 *     2: This is line two
 *     3: This is line three
 *     4: And so on...
 */

static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
    VALUE str, rs;
    long limit;

    RETURN_ENUMERATOR(io, argc, argv);
    prepare_getline_args(argc, argv, &rs, &limit, io);
    while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
    rb_yield(str);
    }
    return io;
}

- (Boolean) eof - (Boolean) eof?

Returns true if ios is at end of file that means there are no more data to read. The stream must be opened for reading or an IOError will be raised.

f = File.new("testfile")
dummy = f.readlines
f.eof   #=> true

If ios is a stream such as pipe or socket, IO#eof? blocks until the other end sends some data or closes it.

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

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

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

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

Overloads:

  • - (Boolean) eof

    Returns:

    • (Boolean)
  • - (Boolean) eof?

    Returns:

    • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.eof     -> true or false
 *     ios.eof?    -> true or false
 *
 *  Returns true if <em>ios</em> is at end of file that means
 *  there are no more data to read.
 *  The stream must be opened for reading or an <code>IOError</code> will be
 *  raised.
 *
 *     f = File.new("testfile")
 *     dummy = f.readlines
 *     f.eof   #=> true
 *
 *  If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
 *  blocks until the other end sends some data or closes it.
 *
 *     r, w = IO.pipe
 *     Thread.new { sleep 1; w.close }
 *     r.eof?  #=> true after 1 second blocking
 *
 *     r, w = IO.pipe
 *     Thread.new { sleep 1; w.puts "a" }
 *     r.eof?  #=> false after 1 second blocking
 *
 *     r, w = IO.pipe
 *     r.eof?  # blocks forever
 *
 *  Note that <code>IO#eof?</code> reads data to the input byte buffer.
 *  So <code>IO#sysread</code> may not behave as you intend with
 *  <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
 *  first (which is not available for some streams).
 */

VALUE
rb_io_eof(VALUE io)
{
    rb_io_t *fptr;

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

    if (READ_CHAR_PENDING(fptr)) return Qfalse;
    if (READ_DATA_PENDING(fptr)) return Qfalse;
    READ_CHECK(fptr);
    if (io_fillbuf(fptr) < 0) {
    return Qtrue;
    }
    return Qfalse;
}

- (Boolean) eof - (Boolean) eof?

Returns true if ios is at end of file that means there are no more data to read. The stream must be opened for reading or an IOError will be raised.

f = File.new("testfile")
dummy = f.readlines
f.eof   #=> true

If ios is a stream such as pipe or socket, IO#eof? blocks until the other end sends some data or closes it.

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

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

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

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

Overloads:

  • - (Boolean) eof

    Returns:

    • (Boolean)
  • - (Boolean) eof?

    Returns:

    • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.eof     -> true or false
 *     ios.eof?    -> true or false
 *
 *  Returns true if <em>ios</em> is at end of file that means
 *  there are no more data to read.
 *  The stream must be opened for reading or an <code>IOError</code> will be
 *  raised.
 *
 *     f = File.new("testfile")
 *     dummy = f.readlines
 *     f.eof   #=> true
 *
 *  If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
 *  blocks until the other end sends some data or closes it.
 *
 *     r, w = IO.pipe
 *     Thread.new { sleep 1; w.close }
 *     r.eof?  #=> true after 1 second blocking
 *
 *     r, w = IO.pipe
 *     Thread.new { sleep 1; w.puts "a" }
 *     r.eof?  #=> false after 1 second blocking
 *
 *     r, w = IO.pipe
 *     r.eof?  # blocks forever
 *
 *  Note that <code>IO#eof?</code> reads data to the input byte buffer.
 *  So <code>IO#sysread</code> may not behave as you intend with
 *  <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
 *  first (which is not available for some streams).
 */

VALUE
rb_io_eof(VALUE io)
{
    rb_io_t *fptr;

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

    if (READ_CHAR_PENDING(fptr)) return Qfalse;
    if (READ_DATA_PENDING(fptr)) return Qfalse;
    READ_CHECK(fptr);
    if (io_fillbuf(fptr) < 0) {
    return Qtrue;
    }
    return Qfalse;
}

- (Encoding) external_encoding

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     io.external_encoding   -> encoding
 *
 *  Returns the Encoding object that represents the encoding of the file.
 *  If io is write mode and no encoding is specified, returns <code>nil</code>.
 */

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

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

- (Integer) fcntl(integer_cmd, arg)

Provides a mechanism for issuing low-level commands to control or query file-oriented I/O streams. Arguments and results are platform dependent. If arg is a number, its value is passed directly. If it is a string, it is interpreted as a binary sequence of bytes (Array#pack might be a useful way to build this string). On Unix platforms, see fcntl(2) for details. Not implemented on all platforms.

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.fcntl(integer_cmd, arg)    -> integer
 *
 *  Provides a mechanism for issuing low-level commands to control or
 *  query file-oriented I/O streams. Arguments and results are platform
 *  dependent. If <i>arg</i> is a number, its value is passed
 *  directly. If it is a string, it is interpreted as a binary sequence
 *  of bytes (<code>Array#pack</code> might be a useful way to build this
 *  string). On Unix platforms, see <code>fcntl(2)</code> for details.
 *  Not implemented on all platforms.
 */

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

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

- (0?) fdatasync

Immediately writes all buffered data in ios to disk.

NotImplementedError is raised if the underlying operating system does not support fdatasync(2).

Returns:

  • (0, nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.fdatasync   -> 0 or nil
 *
 *  Immediately writes all buffered data in <em>ios</em> to disk.
 *
 *  <code>NotImplementedError</code> is raised
 *  if the underlying operating system does not support <em>fdatasync(2)</em>.
 */

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

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

    if (io_fflush(fptr) < 0)
        rb_sys_fail(0);
    if (fdatasync(fptr->fd) < 0)
    rb_sys_fail_path(fptr->pathv);
    return INT2FIX(0);
}

- (Fixnum) fileno - (Fixnum) to_i

Returns an integer representing the numeric file descriptor for ios.

$stdin.fileno    #=> 0
$stdout.fileno   #=> 1

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.fileno    -> fixnum
 *     ios.to_i      -> fixnum
 *
 *  Returns an integer representing the numeric file descriptor for
 *  <em>ios</em>.
 *
 *     $stdin.fileno    #=> 0
 *     $stdout.fileno   #=> 1
 */

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

    GetOpenFile(io, fptr);
    fd = fptr->fd;
    return INT2FIX(fd);
}

- (IO) flush

Flushes any buffered data within ios to the underlying operating system (note that this is Ruby internal buffering only; the OS may buffer the data as well).

$stdout.print "no newline"
$stdout.flush

produces:

no newline

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.flush    -> ios
 *
 *  Flushes any buffered data within <em>ios</em> to the underlying
 *  operating system (note that this is Ruby internal buffering only;
 *  the OS may buffer the data as well).
 *
 *     $stdout.print "no newline"
 *     $stdout.flush
 *
 *  <em>produces:</em>
 *
 *     no newline
 */

VALUE
rb_io_flush(VALUE io)
{
    rb_io_t *fptr;

    if (TYPE(io) != T_FILE) {
        return rb_funcall(io, id_flush, 0);
    }

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

    if (fptr->mode & FMODE_WRITABLE) {
        if (io_fflush(fptr) < 0)
            rb_sys_fail(0);
#ifdef _WIN32
    fsync(fptr->fd);
#endif
    }
    if (fptr->mode & FMODE_READABLE) {
        io_unread(fptr);
    }

    return io;
}

- (0?) fsync

Immediately writes all buffered data in ios to disk. Note that fsync differs from using IO#sync=. The latter ensures that data is flushed from Ruby's buffers, but doesn't not guarantee that the underlying operating system actually writes it to disk.

NotImplementedError is raised if the underlying operating system does not support fsync(2).

Returns:

  • (0, nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.fsync   -> 0 or nil
 *
 *  Immediately writes all buffered data in <em>ios</em> to disk.
 *  Note that <code>fsync</code> differs from
 *  using <code>IO#sync=</code>. The latter ensures that data is flushed
 *  from Ruby's buffers, but doesn't not guarantee that the underlying
 *  operating system actually writes it to disk.
 *
 *  <code>NotImplementedError</code> is raised
 *  if the underlying operating system does not support <em>fsync(2)</em>.
 */

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

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

    if (io_fflush(fptr) < 0)
        rb_sys_fail(0);
    if (fsync(fptr->fd) < 0)
    rb_sys_fail_path(fptr->pathv);
    return INT2FIX(0);
}

- (Fixnum?) getbyte

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.getbyte   -> fixnum or nil
 *
 *  Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
 *  <code>nil</code> if called at end of file.
 *
 *     f = File.new("testfile")
 *     f.getbyte   #=> 84
 *     f.getbyte   #=> 104
 */

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

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    READ_CHECK(fptr);
    if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
        rb_io_t *ofp;
        GetOpenFile(rb_stdout, ofp);
        if (ofp->mode & FMODE_TTY) {
            rb_io_flush(rb_stdout);
        }
    }
    if (io_fillbuf(fptr) < 0) {
    return Qnil;
    }
    fptr->rbuf_off++;
    fptr->rbuf_len--;
    c = (unsigned char)fptr->rbuf[fptr->rbuf_off-1];
    return INT2FIX(c & 0xff);
}

- (String?) getc

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.getc   -> string or nil
 *
 *  Reads a one-character string from <em>ios</em>. Returns
 *  <code>nil</code> if called at end of file.
 *
 *     f = File.new("testfile")
 *     f.getc   #=> "h"
 *     f.getc   #=> "e"
 */

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

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

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

- (String?) gets(sep = $/) - (String?) gets(limit) - (String?) gets(sep, limit)

Reads the next "line'' from the I/O stream; lines are separated by sep. A separator of nil reads the entire contents, and a zero-length separator reads the input a paragraph at a time (two successive newlines in the input separate paragraphs). The stream must be opened for reading or an IOError will be raised. The line read in will be returned and also assigned to $_. Returns nil if called at end of file. If the first argument is an integer, or optional second argument is given, the returning string would not be longer than the given value in bytes.

File.new("testfile").gets   #=> "This is line one\n"
$_                          #=> "This is line one\n"

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.gets(sep=$/)     -> string or nil
 *     ios.gets(limit)      -> string or nil
 *     ios.gets(sep, limit) -> string or nil
 *
 *  Reads the next ``line'' from the I/O stream; lines are separated by
 *  <i>sep</i>. A separator of <code>nil</code> reads the entire
 *  contents, and a zero-length separator reads the input a paragraph at
 *  a time (two successive newlines in the input separate paragraphs).
 *  The stream must be opened for reading or an <code>IOError</code>
 *  will be raised. The line read in will be returned and also assigned
 *  to <code>$_</code>. Returns <code>nil</code> if called at end of
 *  file.  If the first argument is an integer, or optional second
 *  argument is given, the returning string would not be longer than the
 *  given value in bytes.
 *
 *     File.new("testfile").gets   #=> "This is line one\n"
 *     $_                          #=> "This is line one\n"
 */

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

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

    return str;
}

- (Object) initialize_copy

:nodoc:



# File 'io.c'

/* :nodoc: */
static VALUE
rb_io_init_copy(VALUE dest, VALUE io)
{
    rb_io_t *fptr, *orig;
    int fd;
    VALUE write_io;
    off_t pos;

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

    rb_io_flush(io);

    /* copy rb_io_t structure */
    fptr->mode = orig->mode & ~FMODE_PREP;
    fptr->encs = orig->encs;
    fptr->pid = orig->pid;
    fptr->lineno = orig->lineno;
    if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
    fptr->finalize = orig->finalize;
#if defined (__CYGWIN__) || !defined(HAVE_FORK)
    if (fptr->finalize == pipe_finalize)
    pipe_add_fptr(fptr);
#endif

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

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

    return dest;
}

- (String) inspect

Return a string describing this IO object.

Returns:



# File 'io.c'

/*
 * call-seq:
 *   ios.inspect   -> string
 *
 * Return a string describing this IO object.
 */

static VALUE
rb_io_inspect(VALUE obj)
{
    rb_io_t *fptr;
    const char *cname;
    char fd_desc[4+sizeof(int)*3];
    const char *path;
    const char *st = "";

    fptr = RFILE(rb_io_taint_check(obj))->fptr;
    if (!fptr) return rb_any_to_s(obj);
    cname = rb_obj_classname(obj);
    if (NIL_P(fptr->pathv)) {
        if (fptr->fd < 0) {
            path = "";
            st = "(closed)";
        }
        else {
            snprintf(fd_desc, sizeof(fd_desc), "fd %d", fptr->fd);
            path = fd_desc;
        }
    }
    else {
        path = RSTRING_PTR(fptr->pathv);
        if (fptr->fd < 0) {
            st = " (closed)";
        }
    }
    return rb_sprintf("#<%s:%s%s>", cname, path, st);
}

- (Encoding) internal_encoding

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     io.internal_encoding   -> encoding
 *
 *  Returns the Encoding of the internal string if conversion is
 *  specified.  Otherwise returns nil.
 */

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

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

- (Integer) ioctl(integer_cmd, arg)

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

Returns:



# File 'io.c'

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

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

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

- (Boolean) isatty - (Boolean) tty?

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

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

Overloads:

  • - (Boolean) isatty

    Returns:

    • (Boolean)
  • - (Boolean) tty?

    Returns:

    • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.isatty   -> true or false
 *     ios.tty?     -> true or false
 *
 *  Returns <code>true</code> if <em>ios</em> is associated with a
 *  terminal device (tty), <code>false</code> otherwise.
 *
 *     File.new("testfile").isatty   #=> false
 *     File.new("/dev/tty").isatty   #=> true
 */

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

    GetOpenFile(io, fptr);
    if (isatty(fptr->fd) == 0)
    return Qfalse;
    return Qtrue;
}

- (Integer) lineno

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.lineno    -> integer
 *
 *  Returns the current line number in <em>ios</em>. The stream must be
 *  opened for reading. <code>lineno</code> counts the number of times
 *  <code>gets</code> is called, rather than the number of newlines
 *  encountered. The two values will differ if <code>gets</code> is
 *  called with a separator other than newline. See also the
 *  <code>$.</code> variable.
 *
 *     f = File.new("testfile")
 *     f.lineno   #=> 0
 *     f.gets     #=> "This is line one\n"
 *     f.lineno   #=> 1
 *     f.gets     #=> "This is line two\n"
 *     f.lineno   #=> 2
 */

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

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

- (Integer) lineno=(integer)

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.lineno = integer    -> integer
 *
 *  Manually sets the current line number to the given value.
 *  <code>$.</code> is updated only on the next read.
 *
 *     f = File.new("testfile")
 *     f.gets                     #=> "This is line one\n"
 *     $.                         #=> 1
 *     f.lineno = 1000
 *     f.lineno                   #=> 1000
 *     $.                         #=> 1         # lineno of last read
 *     f.gets                     #=> "This is line two\n"
 *     $.                         #=> 1001      # lineno of last read
 */

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

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

- (IO) each(sep = $/) {|line| ... } - (IO) each(limit) {|line| ... } - (IO) each(sep, limit) {|line| ... } - (Object) each(...)

ios.each_line(sep=$/) {|line| block } -> ios

ios.each_line(limit) {|line| block }     -> ios
ios.each_line(sep,limit) {|line| block } -> ios
ios.each_line(...)                       -> an_enumerator

ios.lines(sep=$/) {|line| block }        -> ios
ios.lines(limit) {|line| block }         -> ios
ios.lines(sep,limit) {|line| block }     -> ios
ios.lines(...)                           -> an_enumerator

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

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

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

produces:

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

Overloads:

  • - (IO) each(sep = $/) {|line| ... }

    Yields:

    • (line)

    Returns:

  • - (IO) each(limit) {|line| ... }

    Yields:

    • (line)

    Returns:

  • - (IO) each(sep, limit) {|line| ... }

    Yields:

    • (line)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.each(sep=$/) {|line| block }         -> ios
 *     ios.each(limit) {|line| block }          -> ios
 *     ios.each(sep,limit) {|line| block }      -> ios
 *     ios.each(...)                            -> an_enumerator
 *
 *     ios.each_line(sep=$/) {|line| block }    -> ios
 *     ios.each_line(limit) {|line| block }     -> ios
 *     ios.each_line(sep,limit) {|line| block } -> ios
 *     ios.each_line(...)                       -> an_enumerator
 *
 *     ios.lines(sep=$/) {|line| block }        -> ios
 *     ios.lines(limit) {|line| block }         -> ios
 *     ios.lines(sep,limit) {|line| block }     -> ios
 *     ios.lines(...)                           -> an_enumerator
 *
 *  Executes the block for every line in <em>ios</em>, where lines are
 *  separated by <i>sep</i>. <em>ios</em> must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *  If no block is given, an enumerator is returned instead.
 *
 *     f = File.new("testfile")
 *     f.each {|line| puts "#{f.lineno}: #{line}" }
 *
 *  <em>produces:</em>
 *
 *     1: This is line one
 *     2: This is line two
 *     3: This is line three
 *     4: And so on...
 */

static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
    VALUE str, rs;
    long limit;

    RETURN_ENUMERATOR(io, argc, argv);
    prepare_getline_args(argc, argv, &rs, &limit, io);
    while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
    rb_yield(str);
    }
    return io;
}

- (Fixnum) pid

Returns the process ID of a child process associated with ios. This will be set by IO.popen.

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

produces:

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.pid    -> fixnum
 *
 *  Returns the process ID of a child process associated with
 *  <em>ios</em>. This will be set by <code>IO.popen</code>.
 *
 *     pipe = IO.popen("-")
 *     if pipe
 *       $stderr.puts "In parent, child pid is #{pipe.pid}"
 *     else
 *       $stderr.puts "In child, pid is #{$$}"
 *     end
 *
 *  <em>produces:</em>
 *
 *     In child, pid is 26209
 *     In parent, child pid is 26209
 */

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

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

- (Integer) pos - (Integer) tell

Returns the current offset (in bytes) of ios.

f = File.new("testfile")
f.pos    #=> 0
f.gets   #=> "This is line one\n"
f.pos    #=> 17

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.pos     -> integer
 *     ios.tell    -> integer
 *
 *  Returns the current offset (in bytes) of <em>ios</em>.
 *
 *     f = File.new("testfile")
 *     f.pos    #=> 0
 *     f.gets   #=> "This is line one\n"
 *     f.pos    #=> 17
 */

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

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

- (Integer) pos=(integer)

Seeks to the given position (in bytes) in ios.

f = File.new("testfile")
f.pos = 17
f.gets   #=> "This is line two\n"

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.pos = integer    -> integer
 *
 *  Seeks to the given position (in bytes) in <em>ios</em>.
 *
 *     f = File.new("testfile")
 *     f.pos = 17
 *     f.gets   #=> "This is line two\n"
 */

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

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

    return OFFT2NUM(pos);
}

Writes the given object(s) to ios. The stream must be opened for writing. If the output field separator ($,) is not nil, it will be inserted between each object. If the output record separator ($\</code>) is not <code>nil, it will be appended to the output. If no arguments are given, prints $_. Objects that aren't strings will be converted by calling their to_s method. With no argument, prints the contents of the variable $_. Returns nil.

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

produces:

This is 100 percent.

Overloads:

  • - (nil) print

    Returns:

    • (nil)
  • - (nil) print(obj, ...)

    Returns:

    • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.print()             -> nil
 *     ios.print(obj, ...)     -> nil
 *
 *  Writes the given object(s) to <em>ios</em>. The stream must be
 *  opened for writing. If the output field separator (<code>$,</code>)
 *  is not <code>nil</code>, it will be inserted between each object.
 *  If the output record separator (<code>$\\</code>)
 *  is not <code>nil</code>, it will be appended to the output. If no
 *  arguments are given, prints <code>$_</code>. Objects that aren't
 *  strings will be converted by calling their <code>to_s</code> method.
 *  With no argument, prints the contents of the variable <code>$_</code>.
 *  Returns <code>nil</code>.
 *
 *     $stdout.print("This is ", 100, " percent.\n")
 *
 *  <em>produces:</em>
 *
 *     This is 100 percent.
 */

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

    /* if no argument given, print `$_' */
    if (argc == 0) {
    argc = 1;
    line = rb_lastline_get();
    argv = &line;
    }
    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;
}

- (nil) printf(format_string[, obj, ...])

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

Returns:

  • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.printf(format_string [, obj, ...] )   -> nil
 *
 *  Formats and writes to <em>ios</em>, converting parameters under
 *  control of the format string. See <code>Kernel#sprintf</code>
 *  for details.
 */

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

- (Object) putc(obj)

If obj is Numeric, write the character whose code is the least-significant byte of obj, otherwise write the first byte of the string representation of obj to ios. Note: This method is not safe for use with multi-byte characters as it will truncate them.

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

produces:

AA

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.putc(obj)    -> obj
 *
 *  If <i>obj</i> is <code>Numeric</code>, write the character whose code is
 *  the least-significant byte of <i>obj</i>, otherwise write the first byte
 *  of the string representation of <i>obj</i> to <em>ios</em>. Note: This
 *  method is not safe for use with multi-byte characters as it will truncate
 *  them.
 *
 *     $stdout.putc "A"
 *     $stdout.putc 65
 *
 *  <em>produces:</em>
 *
 *     AA
 */

static VALUE
rb_io_putc(VALUE io, VALUE ch)
{
    char c = NUM2CHR(ch);

    rb_io_write(io, rb_str_new(&c, 1));
    return ch;
}

- (nil) puts(obj, ...)

Writes the given objects to ios as with IO#print. Writes a record separator (typically a newline) after any that do not already end with a newline sequence. If called with an array argument, writes each element on a new line. If called without arguments, outputs a single record separator.

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

produces:

this
is
a
test

Returns:

  • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.puts(obj, ...)    -> nil
 *
 *  Writes the given objects to <em>ios</em> as with
 *  <code>IO#print</code>. Writes a record separator (typically a
 *  newline) after any that do not already end with a newline sequence.
 *  If called with an array argument, writes each element on a new line.
 *  If called without arguments, outputs a single record separator.
 *
 *     $stdout.puts("this", "is", "a", "test")
 *
 *  <em>produces:</em>
 *
 *     this
 *     is
 *     a
 *     test
 */

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

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

    return Qnil;
}

- (String?) read([length [, buffer]])

Reads length bytes from the I/O stream.

length must be a non-negative integer or nil.

If length is a positive integer, it try to read length bytes without any conversion (binary mode). It returns nil or a string whose length is 1 to length bytes. nil means it met EOF at beginning. The 1 to length-1 bytes string means it met EOF after reading the result. The length bytes string means it doesn't meet EOF. The resulted string is always ASCII-8BIT encoding.

If length is omitted or is nil, it reads until EOF and the encoding conversion is applied. It returns a string even if EOF is met at beginning.

If length is zero, it returns "".

If the optional buffer argument is present, it must reference a String, which will receive the data.

At end of file, it returns nil or "" depend on length. ios.read() and ios.read(nil) returns "". ios.read(positive-integer) returns nil.

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

# reads whole file
open("file") {|f|
  data = f.read # This returns a string even if the file is empty.
  ...
}

# iterate over fixed length records.
open("fixed-record-file") {|f|
  while record = f.read(256)
    ...
  end
}

# iterate over variable length records.
# record is prefixed by 32-bit length.
open("variable-record-file") {|f|
  while len = f.read(4)
    len = len.unpack("N")[0] # 32-bit length
    record = f.read(len) # This returns a string even if len is 0.
  end
}

Note that this method behaves like fread() function in C. If you need the behavior like read(2) system call, consider readpartial, read_nonblock and sysread.

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.read([length [, buffer]])    -> string, buffer, or nil
 *
 *  Reads <i>length</i> bytes from the I/O stream.
 *
 *  <i>length</i> must be a non-negative integer or <code>nil</code>.
 *
 *  If <i>length</i> is a positive integer,
 *  it try to read <i>length</i> bytes without any conversion (binary mode).
 *  It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
 *  <code>nil</code> means it met EOF at beginning.
 *  The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result.
 *  The <i>length</i> bytes string means it doesn't meet EOF.
 *  The resulted string is always ASCII-8BIT encoding.
 *
 *  If <i>length</i> is omitted or is <code>nil</code>,
 *  it reads until EOF and the encoding conversion is applied.
 *  It returns a string even if EOF is met at beginning.
 *
 *  If <i>length</i> is zero, it returns <code>""</code>.
 *
 *  If the optional <i>buffer</i> argument is present, it must reference
 *  a String, which will receive the data.
 *
 *  At end of file, it returns <code>nil</code> or <code>""</code>
 *  depend on <i>length</i>.
 *  <code><i>ios</i>.read()</code> and
 *  <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
 *  <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.
 *
 *     f = File.new("testfile")
 *     f.read(16)   #=> "This is line one"
 *
 *     # reads whole file
 *     open("file") {|f|
 *       data = f.read # This returns a string even if the file is empty.
 *       ...
 *     }
 *
 *     # iterate over fixed length records.
 *     open("fixed-record-file") {|f|
 *       while record = f.read(256)
 *         ...
 *       end
 *     }
 *
 *     # iterate over variable length records.
 *     # record is prefixed by 32-bit length.
 *     open("variable-record-file") {|f|
 *       while len = f.read(4)
 *         len = len.unpack("N")[0] # 32-bit length
 *         record = f.read(len) # This returns a string even if len is 0.
 *       end
 *     }
 *
 *  Note that this method behaves like fread() function in C.
 *  If you need the behavior like read(2) system call,
 *  consider readpartial, read_nonblock and sysread.
 */

static VALUE
io_read(int argc, VALUE *argv, VALUE io)
{
    rb_io_t *fptr;
    long n, len;
    VALUE length, str;

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

    io_setstrbuf(&str,len);

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    if (len == 0) return str;

    READ_CHECK(fptr);
    n = io_fread(str, 0, fptr);
    if (n == 0) {
    if (fptr->fd < 0) return Qnil;
        rb_str_resize(str, 0);
        return Qnil;
    }
    rb_str_resize(str, n);
    OBJ_TAINT(str);

    return str;
}

- (String) read_nonblock(maxlen) - (Object) read_nonblock(maxlen, outbuf)

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

If the optional outbuf argument is present, it must reference a String, which will receive the data.

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::AGAIN, it is extended by IO::WaitReadable. So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.

read_nonblock causes EOFError on EOF.

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

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

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

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

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

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.read_nonblock(maxlen)              -> string
 *     ios.read_nonblock(maxlen, outbuf)      -> outbuf
 *
 *  Reads at most <i>maxlen</i> bytes from <em>ios</em> using
 *  the read(2) system call after O_NONBLOCK is set for
 *  the underlying file descriptor.
 *
 *  If the optional <i>outbuf</i> argument is present,
 *  it must reference a String, which will receive the data.
 *
 *  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::AGAIN,
 *  it is extended by IO::WaitReadable.
 *  So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
 *
 *  read_nonblock causes EOFError on EOF.
 *
 *  If the read byte buffer is not empty,
 *  read_nonblock reads from the buffer like readpartial.
 *  In this case, the read(2) system call is not called.
 *
 *  When read_nonblock raises an exception kind of IO::WaitReadable,
 *  read_nonblock should not be called
 *  until io is readable for avoiding busy loop.
 *  This can be done as follows.
 *
 *    # emulates blocking read (readpartial).
 *    begin
 *      result = io.read_nonblock(maxlen)
 *    rescue IO::WaitReadable
 *      IO.select([io])
 *      retry
 *    end
 *
 *  Although IO#read_nonblock doesn't raise IO::WaitWritable.
 *  OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable.
 *  If IO and SSL should be used polymorphically,
 *  IO::WaitWritable should be rescued too.
 *  See the document of OpenSSL::Buffering#read_nonblock for sample code.
 *
 *  Note that this method is identical to readpartial
 *  except the non-blocking flag is set.
 */

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

    ret = io_getpartial(argc, argv, io, 1);
    if (NIL_P(ret))
        rb_eof_error();
    else
        return ret;
}

- (Fixnum) readbyte

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.readbyte   -> fixnum
 *
 *  Reads a byte as with <code>IO#getbyte</code>, but raises an
 *  <code>EOFError</code> on end of file.
 */

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

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

- (String) readchar

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.readchar   -> string
 *
 *  Reads a one-character string from <em>ios</em>. Raises an
 *  <code>EOFError</code> on end of file.
 *
 *     f = File.new("testfile")
 *     f.readchar   #=> "h"
 *     f.readchar   #=> "e"
 */

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

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

- (String) readline(sep = $/) - (String) readline(limit) - (String) readline(sep, limit)

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

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.readline(sep=$/)     -> string
 *     ios.readline(limit)      -> string
 *     ios.readline(sep, limit) -> string
 *
 *  Reads a line as with <code>IO#gets</code>, but raises an
 *  <code>EOFError</code> on end of file.
 */

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

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

- (Array) readlines(sep = $/) - (Array) readlines(limit) - (Array) readlines(sep, limit)

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

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

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.readlines(sep=$/)     -> array
 *     ios.readlines(limit)      -> array
 *     ios.readlines(sep, limit) -> array
 *
 *  Reads all of the lines in <em>ios</em>, and returns them in
 *  <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
 *  <i>sep</i> is <code>nil</code>, the rest of the stream is returned
 *  as a single record.  If the first argument is an integer, or
 *  optional second argument is given, the returning string would not be
 *  longer than the given value in bytes. The stream must be opened for
 *  reading or an <code>IOError</code> will be raised.
 *
 *     f = File.new("testfile")
 *     f.readlines[0]   #=> "This is line one\n"
 */

static VALUE
rb_io_readlines(int argc, VALUE *argv, VALUE io)
{
    VALUE line, ary, rs;
    long limit;

    prepare_getline_args(argc, argv, &rs, &limit, io);
    ary = rb_ary_new();
    while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
    rb_ary_push(ary, line);
    }
    return ary;
}

- (String) readpartial(maxlen) - (Object) readpartial(maxlen, outbuf)

Reads at most maxlen bytes from the I/O stream. It blocks only if ios has no data immediately available. It doesn't block if some data available. If the optional outbuf argument is present, it must reference a String, which will receive the data. It raises EOFError on end of file.

readpartial is designed for streams such as pipe, socket, tty, etc. It blocks only when no data immediately available. This means that it blocks only when following all conditions hold.

  • the byte buffer in the IO object is empty.

  • the content of the stream is empty.

  • the stream is not reached to EOF.

When readpartial blocks, it waits data or EOF on the stream. If some data is reached, readpartial returns with the data. If EOF is reached, readpartial raises EOFError.

When readpartial doesn't blocks, it returns or raises immediately. If the byte buffer is not empty, it returns the data in the buffer. Otherwise if the stream has some content, it returns the data in the stream. Otherwise if the stream is reached to EOF, it raises EOFError.

r, w = IO.pipe           #               buffer          pipe content
w << "abc"               #               ""              "abc".
r.readpartial(4096)      #=> "abc"       ""              ""
r.readpartial(4096)      # blocks because buffer and pipe is empty.

r, w = IO.pipe           #               buffer          pipe content
w << "abc"               #               ""              "abc"
w.close                  #               ""              "abc" EOF
r.readpartial(4096)      #=> "abc"       ""              EOF
r.readpartial(4096)      # raises EOFError

r, w = IO.pipe           #               buffer          pipe content
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"     ""              ""

Note that readpartial behaves similar to sysread. The differences are:

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

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

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

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.readpartial(maxlen)              -> string
 *     ios.readpartial(maxlen, outbuf)      -> outbuf
 *
 *  Reads at most <i>maxlen</i> bytes from the I/O stream.
 *  It blocks only if <em>ios</em> has no data immediately available.
 *  It doesn't block if some data available.
 *  If the optional <i>outbuf</i> argument is present,
 *  it must reference a String, which will receive the data.
 *  It raises <code>EOFError</code> on end of file.
 *
 *  readpartial is designed for streams such as pipe, socket, tty, etc.
 *  It blocks only when no data immediately available.
 *  This means that it blocks only when following all conditions hold.
 *  * the byte buffer in the IO object is empty.
 *  * the content of the stream is empty.
 *  * the stream is not reached to EOF.
 *
 *  When readpartial blocks, it waits data or EOF on the stream.
 *  If some data is reached, readpartial returns with the data.
 *  If EOF is reached, readpartial raises EOFError.
 *
 *  When readpartial doesn't blocks, it returns or raises immediately.
 *  If the byte buffer is not empty, it returns the data in the buffer.
 *  Otherwise if the stream has some content,
 *  it returns the data in the stream.
 *  Otherwise if the stream is reached to EOF, it raises EOFError.
 *
 *     r, w = IO.pipe           #               buffer          pipe content
 *     w << "abc"               #               ""              "abc".
 *     r.readpartial(4096)      #=> "abc"       ""              ""
 *     r.readpartial(4096)      # blocks because buffer and pipe is empty.
 *
 *     r, w = IO.pipe           #               buffer          pipe content
 *     w << "abc"               #               ""              "abc"
 *     w.close                  #               ""              "abc" EOF
 *     r.readpartial(4096)      #=> "abc"       ""              EOF
 *     r.readpartial(4096)      # raises EOFError
 *
 *     r, w = IO.pipe           #               buffer          pipe content
 *     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"     ""              ""
 *
 *  Note that readpartial behaves similar to sysread.
 *  The differences are:
 *  * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
 *  * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR.  When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
 *
 *  The later means that readpartial is nonblocking-flag insensitive.
 *  It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
 *
 */

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

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

- (IO) reopen(other_IO) - (IO) reopen(path, mode_str)

Reassociates ios with the I/O stream given in other_IO or to a new stream opened on path. This may dynamically change the actual class of this stream.

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

Overloads:

  • - (IO) reopen(other_IO)

    Returns:

  • - (IO) reopen(path, mode_str)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.reopen(other_IO)         -> ios
 *     ios.reopen(path, mode_str)   -> ios
 *
 *  Reassociates <em>ios</em> with the I/O stream given in
 *  <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
 *  dynamically change the actual class of this stream.
 *
 *     f1 = File.new("testfile")
 *     f2 = File.new("testfile")
 *     f2.readlines[0]   #=> "This is line one\n"
 *     f2.reopen(f1)     #=> #<File:testfile>
 *     f2.readlines[0]   #=> "This is line one\n"
 */

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

    rb_secure(4);
    if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 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 = ALLOC(rb_io_t);
    MEMZERO(fptr, rb_io_t, 1);
    }

    if (!NIL_P(nmode)) {
    int fmode = rb_io_modestr_fmode(StringValueCStr(nmode));
    if (IS_PREP_STDIO(fptr) &&
            ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
            (fptr->mode & FMODE_READWRITE)) {
        rb_raise(rb_eArgError,
             "%s can't change access mode from \"%s\" to \"%s\"",
             PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
             rb_io_fmode_modestr(fmode));
    }
    fptr->mode = fmode;
    rb_io_mode_enc(fptr, StringValueCStr(nmode));
        fptr->encs.ecflags = 0;
        fptr->encs.ecopts = Qnil;
    }

    fptr->pathv = rb_str_new_frozen(fname);
    oflags = rb_io_fmode_oflags(fptr->mode);
    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(0);
    }
    fptr->rbuf_off = fptr->rbuf_len = 0;

    if (fptr->stdio_file) {
        if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
            rb_sys_fail_path(fptr->pathv);
        }
        fptr->fd = fileno(fptr->stdio_file);
#ifdef USE_SETVBUF
        if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
            rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
#endif
    }
    else {
        if (close(fptr->fd) < 0)
            rb_sys_fail_path(fptr->pathv);
        fptr->fd = -1;
        fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
    }

    return file;
}

- (0) rewind

Positions ios to the beginning of input, resetting lineno to zero.

f = File.new("testfile")
f.readline   #=> "This is line one\n"
f.rewind     #=> 0
f.lineno     #=> 0
f.readline   #=> "This is line one\n"

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

Returns:

  • (0)


# File 'io.c'

/*
 *  call-seq:
 *     ios.rewind    -> 0
 *
 *  Positions <em>ios</em> to the beginning of input, resetting
 *  <code>lineno</code> to zero.
 *
 *     f = File.new("testfile")
 *     f.readline   #=> "This is line one\n"
 *     f.rewind     #=> 0
 *     f.lineno     #=> 0
 *     f.readline   #=> "This is line one\n"
 *
 *  Note that it cannot be used with streams such as pipes, ttys, and sockets.
 */

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

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

    return INT2FIX(0);
}

- (0) seek(amount, whence = IO::SEEK_SET)

Seeks to a given offset anInteger in the stream according to the value of whence:

IO::SEEK_CUR  | Seeks to _amount_ plus current position
--------------+----------------------------------------------------
IO::SEEK_END  | Seeks to _amount_ plus end of stream (you probably
              | want a negative value for _amount_)
--------------+----------------------------------------------------
IO::SEEK_SET  | Seeks to the absolute location given by _amount_

Example:

f = File.new("testfile")
f.seek(-13, IO::SEEK_END)   #=> 0
f.readline                  #=> "And so on...\n"

Returns:

  • (0)


# File 'io.c'

/*
 *  call-seq:
 *     ios.seek(amount, whence=IO::SEEK_SET)  ->  0
 *
 *  Seeks to a given offset <i>anInteger</i> in the stream according to
 *  the value of <i>whence</i>:
 *
 *    IO::SEEK_CUR  | Seeks to _amount_ plus current position
 *    --------------+----------------------------------------------------
 *    IO::SEEK_END  | Seeks to _amount_ plus end of stream (you probably
 *                  | want a negative value for _amount_)
 *    --------------+----------------------------------------------------
 *    IO::SEEK_SET  | Seeks to the absolute location given by _amount_
 *
 *  Example:
 *
 *     f = File.new("testfile")
 *     f.seek(-13, IO::SEEK_END)   #=> 0
 *     f.readline                  #=> "And so on...\n"
 */

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

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

    return rb_io_seek(io, offset, whence);
}

- (IO) set_encoding(ext_enc) - (IO) set_encoding("ext_enc:int_enc") - (IO) set_encoding(ext_enc, int_enc) - (IO) set_encoding("ext_enc:int_enc", opt) - (IO) set_encoding(ext_enc, int_enc, opt)

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

Overloads:

  • - (IO) set_encoding(ext_enc)

    Returns:

  • - (IO) set_encoding("ext_enc:int_enc")

    Returns:

  • - (IO) set_encoding(ext_enc, int_enc)

    Returns:

  • - (IO) set_encoding("ext_enc:int_enc", opt)

    Returns:

  • - (IO) set_encoding(ext_enc, int_enc, opt)

    Returns:



# File 'io.c'

/*
 *  call-seq:
 *     io.set_encoding(ext_enc)                -> io
 *     io.set_encoding("ext_enc:int_enc")      -> io
 *     io.set_encoding(ext_enc, int_enc)       -> io
 *     io.set_encoding("ext_enc:int_enc", opt) -> io
 *     io.set_encoding(ext_enc, int_enc, opt)  -> io
 *
 *  If single argument is specified, read string from io is tagged
 *  with the encoding specified.  If encoding is a colon separated two
 *  encoding names "A:B", the read string is converted from encoding A
 *  (external encoding) to encoding B (internal encoding), then tagged
 *  with B.  If two arguments are specified, those must be encoding
 *  objects or encoding names, and the first one is the external encoding, and the
 *  second one is the internal encoding.
 *  If the external encoding and the internal encoding is specified,
 *  optional hash argument specify the conversion option.
 */

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

    if (TYPE(io) != T_FILE) {
        return rb_funcall2(io, id_set_encoding, argc, argv);
    }

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

- (Object) stat

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

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


# File 'file.c'

/*
 *  call-seq:
 *     ios.stat    -> stat
 *
 *  Returns status information for <em>ios</em> as an object of type
 *  <code>File::Stat</code>.
 *
 *     f = File.new("testfile")
 *     s = f.stat
 *     "%o" % s.mode   #=> "100644"
 *     s.blksize       #=> 4096
 *     s.atime         #=> Wed Apr 09 08:53:54 CDT 2003
 *
 */

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

#define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
    GetOpenFile(obj, fptr);
    if (fstat(fptr->fd, &st) == -1) {
    rb_sys_fail_path(fptr->pathv);
    }
    return stat_new(&st);
}

- (Boolean) sync

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

f = File.new("testfile")
f.sync   #=> false

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.sync    -> true or false
 *
 *  Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
 *  true, all output is immediately flushed to the underlying operating
 *  system and is not buffered by Ruby internally. See also
 *  <code>IO#fsync</code>.
 *
 *     f = File.new("testfile")
 *     f.sync   #=> false
 */

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

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);
    return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
}

- (Boolean) sync=(boolean)

Sets the "sync mode'' to true or false. When sync mode is true, all output is immediately flushed to the underlying operating system and is not buffered internally. Returns the new state. See also IO#fsync.

f = File.new("testfile")
f.sync = true

(produces no output)

Returns:

  • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.sync = boolean   -> boolean
 *
 *  Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
 *  When sync mode is true, all output is immediately flushed to the
 *  underlying operating system and is not buffered internally. Returns
 *  the new state. See also <code>IO#fsync</code>.
 *
 *     f = File.new("testfile")
 *     f.sync = true
 *
 *  <em>(produces no output)</em>
 */

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

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

- (String) sysread(integer[, outbuf])

Reads integer bytes from ios using a low-level read and returns them as a string. Do not mix with other methods that read from ios or you may get unpredictable results. If the optional outbuf argument is present, it must reference a String, which will receive the data. Raises SystemCallError on error and EOFError at end of file.

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.sysread(integer[, outbuf])    -> string
 *
 *  Reads <i>integer</i> bytes from <em>ios</em> using a low-level
 *  read and returns them as a string. Do not mix with other methods
 *  that read from <em>ios</em> or you may get unpredictable results.
 *  If the optional <i>outbuf</i> argument is present, it must reference
 *  a String, which will receive the data.
 *  Raises <code>SystemCallError</code> on error and
 *  <code>EOFError</code> at end of file.
 *
 *     f = File.new("testfile")
 *     f.sysread(16)   #=> "This is line one"
 */

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

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

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

    n = fptr->fd;
    rb_thread_wait_fd(fptr->fd);
    rb_io_check_closed(fptr);

    rb_str_locktmp(str);
    n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);
    rb_str_unlocktmp(str);

    if (n == -1) {
    rb_sys_fail_path(fptr->pathv);
    }
    rb_str_set_len(str, n);
    if (n == 0 && ilen > 0) {
    rb_eof_error();
    }
    rb_str_resize(str, n);
    OBJ_TAINT(str);

    return str;
}

- (Integer) sysseek(offset, whence = IO::SEEK_SET)

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.sysseek(offset, whence=IO::SEEK_SET)   -> integer
 *
 *  Seeks to a given <i>offset</i> in the stream according to the value
 *  of <i>whence</i> (see <code>IO#seek</code> for values of
 *  <i>whence</i>). Returns the new offset into the file.
 *
 *     f = File.new("testfile")
 *     f.sysseek(-13, IO::SEEK_END)   #=> 53
 *     f.sysread(10)                  #=> "And so on."
 */

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

    if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
    whence = NUM2INT(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 == -1 && errno) rb_sys_fail_path(fptr->pathv);

    return OFFT2NUM(pos);
}

- (Integer) syswrite(string)

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.syswrite(string)   -> integer
 *
 *  Writes the given string to <em>ios</em> using a low-level write.
 *  Returns the number of bytes written. Do not mix with other methods
 *  that write to <em>ios</em> or you may get unpredictable results.
 *  Raises <code>SystemCallError</code> on error.
 *
 *     f = File.new("out", "w")
 *     f.syswrite("ABCDEF")   #=> 6
 */

static VALUE
rb_io_syswrite(VALUE io, VALUE str)
{
    rb_io_t *fptr;
    long n;

    rb_secure(4);
    if (TYPE(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");
    }
    if (!rb_thread_fd_writable(fptr->fd)) {
        rb_io_check_closed(fptr);
    }

    n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));

    if (n == -1) rb_sys_fail_path(fptr->pathv);

    return LONG2FIX(n);
}

- (Integer) pos - (Integer) tell

Returns the current offset (in bytes) of ios.

f = File.new("testfile")
f.pos    #=> 0
f.gets   #=> "This is line one\n"
f.pos    #=> 17

Overloads:



# File 'io.c'

/*
 *  call-seq:
 *     ios.pos     -> integer
 *     ios.tell    -> integer
 *
 *  Returns the current offset (in bytes) of <em>ios</em>.
 *
 *     f = File.new("testfile")
 *     f.pos    #=> 0
 *     f.gets   #=> "This is line one\n"
 *     f.pos    #=> 17
 */

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

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

- (IO) to_io

Returns ios.

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.to_io  ->  ios
 *
 *  Returns <em>ios</em>.
 */

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

- (Boolean) isatty - (Boolean) tty?

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

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

Overloads:

  • - (Boolean) isatty

    Returns:

    • (Boolean)
  • - (Boolean) tty?

    Returns:

    • (Boolean)


# File 'io.c'

/*
 *  call-seq:
 *     ios.isatty   -> true or false
 *     ios.tty?     -> true or false
 *
 *  Returns <code>true</code> if <em>ios</em> is associated with a
 *  terminal device (tty), <code>false</code> otherwise.
 *
 *     File.new("testfile").isatty   #=> false
 *     File.new("/dev/tty").isatty   #=> true
 */

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

    GetOpenFile(io, fptr);
    if (isatty(fptr->fd) == 0)
    return Qfalse;
    return Qtrue;
}

- (nil) ungetbyte(string) - (nil) ungetbyte(integer)

Pushes back bytes (passed as a parameter) onto ios, such that a subsequent buffered read will return it. Only one byte may be pushed back before a subsequent read operation (that is, you will be able to read only the last of several bytes that have been pushed back). Has no effect with unbuffered reads (such as IO#sysread).

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

Overloads:

  • - (nil) ungetbyte(string)

    Returns:

    • (nil)
  • - (nil) ungetbyte(integer)

    Returns:

    • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.ungetbyte(string)   -> nil
 *     ios.ungetbyte(integer)   -> nil
 *
 *  Pushes back bytes (passed as a parameter) onto <em>ios</em>,
 *  such that a subsequent buffered read will return it. Only one byte
 *  may be pushed back before a subsequent read operation (that is,
 *  you will be able to read only the last of several bytes that have been pushed
 *  back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
 *
 *     f = File.new("testfile")   #=> #<File:testfile>
 *     b = f.getbyte              #=> 0x38
 *     f.ungetbyte(b)             #=> nil
 *     f.getbyte                  #=> 0x38
 */

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

    GetOpenFile(io, fptr);
    rb_io_check_byte_readable(fptr);
    if (NIL_P(b)) return Qnil;
    if (FIXNUM_P(b)) {
    char cc = FIX2INT(b);
    b = rb_str_new(&cc, 1);
    }
    else {
    SafeStringValue(b);
    }
    io_ungetbyte(b, fptr);
    return Qnil;
}

- (nil) ungetc(string)

Pushes back one character (passed as a parameter) onto ios, such that a subsequent buffered character read will return it. Only one character may be pushed back before a subsequent read operation (that is, you will be able to read only the last of several characters that have been pushed back). Has no effect with unbuffered reads (such as IO#sysread).

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

Returns:

  • (nil)


# File 'io.c'

/*
 *  call-seq:
 *     ios.ungetc(string)   -> nil
 *
 *  Pushes back one character (passed as a parameter) onto <em>ios</em>,
 *  such that a subsequent buffered character read will return it. Only one character
 *  may be pushed back before a subsequent read operation (that is,
 *  you will be able to read only the last of several characters that have been pushed
 *  back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
 *
 *     f = File.new("testfile")   #=> #<File:testfile>
 *     c = f.getc                 #=> "8"
 *     f.ungetc(c)                #=> nil
 *     f.getc                     #=> "8"
 */

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

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    if (NIL_P(c)) return Qnil;
    if (FIXNUM_P(c)) {
    c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
    }
    else if (TYPE(c) == T_BIGNUM) {
    c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
    }
    else {
    SafeStringValue(c);
    }
    if (NEED_READCONV(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+fptr->cbuf_capa-fptr->cbuf_len,
                    fptr->cbuf+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+fptr->cbuf_off, RSTRING_PTR(c), char, len);
    }
    else {
        io_ungetbyte(c, fptr);
    }
    return Qnil;
}

- (Integer) write(string)

Writes the given string to ios. The stream must be opened for writing. If the argument is not a string, it will be converted to a string using to_s. Returns the number of bytes written.

count = $stdout.write( "This is a test\n" )
puts "That was #{count} bytes of data"

produces:

This is a test
That was 15 bytes of data

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.write(string)    -> integer
 *
 *  Writes the given string to <em>ios</em>. The stream must be opened
 *  for writing. If the argument is not a string, it will be converted
 *  to a string using <code>to_s</code>. Returns the number of bytes
 *  written.
 *
 *     count = $stdout.write( "This is a test\n" )
 *     puts "That was #{count} bytes of data"
 *
 *  <em>produces:</em>
 *
 *     This is a test
 *     That was 15 bytes of data
 */

static VALUE
io_write_m(VALUE io, VALUE str)
{
    return io_write(io, str, 0);
}

- (Integer) write_nonblock(string)

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

It returns the number of bytes written.

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

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

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

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

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

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

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

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

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

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

Returns:



# File 'io.c'

/*
 *  call-seq:
 *     ios.write_nonblock(string)   -> integer
 *
 *  Writes the given string to <em>ios</em> 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::AGAIN,
 *  it is extended by IO::WaitWritable.
 *  So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
 *
 *    # Creates a pipe.
 *    r, w = IO.pipe
 *
 *    # write_nonblock writes only 65536 bytes and return 65536.
 *    # (The pipe size is 65536 bytes on this environment.)
 *    s = "a" * 100000
 *    p w.write_nonblock(s)     #=> 65536
 *
 *    # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
 *    p w.write_nonblock("b")   # Resource temporarily unavailable (Errno::EAGAIN)
 *
 *  If the write buffer is not empty, it is flushed at first.
 *
 *  When write_nonblock raises an exception kind of IO::WaitWritable,
 *  write_nonblock should not be called
 *  until io is writable for avoiding busy loop.
 *  This can be done as follows.
 *
 *    begin
 *      result = io.write_nonblock(string)
 *    rescue IO::WaitWritable, Errno::EINTR
 *      IO.select(nil, [io])
 *      retry
 *    end
 *
 *  Note that this doesn't guarantee to write all data in string.
 *  The length written is reported as result and it should be checked later.
 *
 *  On some platforms such as Windows, write_nonblock is not supported
 *  according to the kind of the IO object.
 *  In such cases, write_nonblock raises <code>Errno::EBADF</code>.
 *
 */

static VALUE
rb_io_write_nonblock(VALUE io, VALUE str)
{
    rb_io_t *fptr;
    long n;

    rb_secure(4);
    if (TYPE(str) != T_STRING)
    str = rb_obj_as_string(str);

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

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

    rb_io_set_nonblock(fptr);
    n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));

    if (n == -1) {
        if (errno == EWOULDBLOCK || errno == EAGAIN)
            rb_mod_sys_fail(rb_mWaitWritable, "write would block");
        rb_sys_fail_path(fptr->pathv);
    }

    return LONG2FIX(n);
}