In Files

  • file.c
  • io.c

IO

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.

Public Class Methods

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

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. 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);
}
            
copy_stream(src, dst) click to toggle source
copy_stream(src, dst, copy_length)
copy_stream(src, dst, copy_length, src_offset)

::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, ::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);
}
            
for_fd(fd, mode [, opt]) => io click to toggle source

Synonym for IO.new.

 
               static VALUE
rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
{
    VALUE io = rb_obj_alloc(klass);
    rb_io_initialize(argc, argv, io);
    return io;
}
            
foreach(name, sep=$/ [, open_args]) {|line| block } => nil click to toggle source
foreach(name, limit [, open_args]) {|line| block } => nil
foreach(name, sep, limit [, open_args]) {|line| block } => nil

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

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.

 
               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);
}
            
new(*args) click to toggle source

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

Parameters ↑

fd

numeric file descriptor

mode

file mode. a string or an integer

opt

hash for specifiying 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.

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 “b” in argument mode.

:binmode

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

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

Example1 ↑

a = IO.new(2,"w")      # '2' is standard error
$stderr.puts "Hello"
a.puts "World"

produces:

Hello
World

Example2 ↑

io = IO.new(2, mode: 'w:UTF-16LE', cr_newline: true)
io.puts "Hello, World!"

io = IO.new(2, mode: 'w', cr_newline: true, external_encoding: Encoding::UTF_16LE)
io.puts "Hello, World!"

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

 
               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);
}
            
open(fd, mode_string="r" [, opt] ) => io click to toggle source
open(fd, mode_string="r" [, opt] ) {|io| block } => obj

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.

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

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 ]. Not available on all platforms.

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

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

rd, wr = IO.pipe

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

produces:

Sending message to parent
Parent got: <Hi Dad>
 
               static VALUE
rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
{
    int pipes[2], state;
    VALUE r, w, args[3], v1, v2;
    VALUE opt;
    rb_io_t *fptr, *fptr2;
    int fmode = 0;

    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;

    return rb_assoc_new(r, w);
}
            
popen(cmd, mode="r" [, opt]) => io click to toggle source
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 IO object. 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