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" |  (DOS/Windows only) Binary file mode (may appear with 
     |  any of the key letters listed above).

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

for_fd(fd, mode) => io click to toggle source

Synonym for IO::new.

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

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

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...
 
               static VALUE
rb_io_s_foreach(argc, argv)
    int argc;
    VALUE *argv;
{
    VALUE fname;
    struct foreach_arg arg;

    rb_scan_args(argc, argv, "11", &fname, &arg.sep);
    SafeStringValue(fname);

    if (argc == 1) {
        arg.sep = rb_default_rs;
    }
    else if (!NIL_P(arg.sep)) {
        StringValue(arg.sep);
    }
    arg.io = rb_io_open(StringValueCStr(fname), "r");
    if (NIL_P(arg.io)) return Qnil;

    return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
}
            
new(fd, mode_string) => io click to toggle source

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

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

produces:

Hello
World
 
               static VALUE
rb_io_s_new(argc, argv, klass)
    int argc;
    VALUE *argv;
    VALUE klass;
{
    if (rb_block_given_p()) {
        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" ) => io click to toggle source
open(fd, mode_string="r" ) {|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(argc, argv, klass)
    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 → array click to toggle source

Creates a pair of pipe endpoints (connected to each other) and returns them as a two-element array of IO objects: [ read_file, write_file ]. Not available on all platforms.

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

rd, wr = IO.pipe

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

produces:

Sending message to parent
Parent got: <Hi Dad>
 
               static VALUE
rb_io_s_pipe(klass)
    VALUE klass;
{
#ifndef __human68k__
    int pipes[2], state;
    VALUE r, w, args[3];

#ifdef _WIN32
    if (_pipe(pipes, 1024, O_BINARY) == -1)
#else
    if (pipe(pipes) == -1)
#endif
        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);
    }
    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);
    }
    rb_io_synchronized(RFILE(w)->fptr);

    return rb_assoc_new(r, w);
#else
    rb_notimplement();
    return Qnil;                /* not reached */
#endif
}
            
popen(cmd_string, mode="r" ) => io click to toggle source
popen(cmd_string, mode="r" ) {|io| block } => obj

Runs the specified command string as a subprocess; the subprocess's standard input and output will be connected to the returned IO object. If cmd_string starts with a “-'', then a new instance of Ruby is started as the subprocess. 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.

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_string 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
puts "Parent is #{Process.pid}"
IO.popen ("date") { |f| puts f.gets }
IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f}"}
p $?

produces:

["Linux\n"]
Parent is 26166
Wed Apr  9 08:53:52 CDT 2003
26169 is here, f is
26166 is here, f is #<IO:0x401b3d44>
#<Process::Status: pid=26166,exited(0)>
 
               static VALUE
rb_io_s_popen(argc, argv, klass)
    int argc;
    VALUE *argv;
    VALUE klass;
{
    char *mode;
    VALUE pname, pmode, port;

    if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
        mode = "r";
    }
    else if (FIXNUM_P(pmode)) {
        mode = rb_io_modenum_mode(FIX2INT(pmode));
    }
    else {
        mode = rb_io_flags_mode(rb_io_mode_flags(StringValueCStr(pmode)));
    }
    SafeStringValue(pname);
    port = pipe_open(pname, 0, mode);
    if (NIL_P(port)) {
        /* child */
        if (rb_block_given_p()) {
            rb_yield(Qnil);
            fflush(stdout);
            fflush(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;
}
            
read(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.

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(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE fname, offset;
    struct foreach_arg arg;

    rb_scan_args(argc, argv, "12", &fname, &arg.sep, &offset);
    SafeStringValue(fname);

    arg.argc = argc ? 1 : 0;
    arg.io = rb_io_open(StringValueCStr(fname), "r");
    if (NIL_P(arg.io)) return Qnil;
    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);
}
            
readlines(name, sep_string=$/) => array click to toggle source

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

a = IO.readlines("testfile")
a[0]   #=> "This is line one\n"
 
               static VALUE
rb_io_s_readlines(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE fname;
    struct foreach_arg arg;

    rb_scan_args(argc, argv, "11", &fname, &arg.sep);
    SafeStringValue(fname);

    arg.argc = argc - 1;
    arg.io = rb_io_open(StringValueCStr(fname), "r");
    if (NIL_P(arg.io)) return Qnil;
    return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
}
            
select(read_array click to toggle source
[, write_array
[, error_array
[, timeout]]] ) => array or nil

See Kernel#select.

 
               static VALUE
rb_f_select(argc, argv, obj)
    int argc;
    VALUE *argv;
    VALUE obj;
{
    VALUE read, write, except, timeout, res, list;
    fd_set rset, wset, eset, pset;
    fd_set *rp, *wp, *ep;
    struct timeval *tp, timerec;
    OpenFile *fptr;
    long i;
    int max = 0, n;
    int interrupt_flag = 0;
    int pending = 0;

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

    FD_ZERO(&pset);
    if (!NIL_P(read)) {
        Check_Type(read, T_ARRAY);
        rp = &rset;
        FD_ZERO(rp);
        for (i=0; i<RARRAY(read)->len; i++) {
            GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
            FD_SET(fileno(fptr->f), rp);
            if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */
                pending++;
                FD_SET(fileno(fptr->f), &pset);
            }
            if (max < fileno(fptr->f)) max = fileno(fptr->f);
        }
        if (pending) {         /* no blocking if there's buffered data */
            timerec.tv_sec = timerec.tv_usec = 0;
            tp = &timerec;
        }
    }
    else
        rp = 0;

    if (!NIL_P(write)) {
        Check_Type(write, T_ARRAY);
        wp = &wset;
        FD_ZERO(wp);
        for (i=0; i<RARRAY(write)->len; i++) {
            GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
            FD_SET(fileno(fptr->f), wp);
            if (max < fileno(fptr->f)) max = fileno(fptr->f);
            if (fptr->f2) {
                FD_SET(fileno(fptr->f2), wp);
                if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
            }
        }
    }
    else
        wp = 0;

    if (!NIL_P(except)) {
        Check_Type(except, T_ARRAY);
        ep = &eset;
        FD_ZERO(ep);
        for (i=0; i<RARRAY(except)->len; i++) {
            GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
            FD_SET(fileno(fptr->f), ep);
            if (max < fileno(fptr->f)) max = fileno(fptr->f);
            if (fptr->f2) {
                FD_SET(fileno(fptr->f2), ep);
                if (max < fileno(fptr->f2)) max = fileno(fptr->f2);
            }
        }
    }
    else {
        ep = 0;
    }

    max++;

    n = rb_thread_select(max, rp, wp, ep, tp);
    if (n < 0) {
        rb_sys_fail(0);
    }
    if (!pending && n == 0) return Qnil; /* returns nil on timeout */

    res = rb_ary_new2(3);
    rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
    rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
    rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));

    if (interrupt_flag == 0) {
        if (rp) {
            list = RARRAY(res)->ptr[0];
            for (i=0; i< RARRAY(read)->len; i++) {
                GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
                if (FD_ISSET(fileno(fptr->f), rp)
                    || FD_ISSET(fileno(fptr->f), &pset)) {
                    rb_ary_push(list, rb_ary_entry(read, i));
                }
            }
        }

        if (wp) {
            list = RARRAY(res)->ptr[1];
            for (i=0; i< RARRAY(write)->len; i++) {
                GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
                if (FD_ISSET(fileno(fptr->f), wp)) {
                    rb_ary_push(list, rb_ary_entry(write, i));
                }
                else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), wp)) {
                    rb_ary_push(list, rb_ary_entry(write, i));
                }
            }
        }

        if (ep) {
            list = RARRAY(res)->ptr[2];
            for (i=0; i< RARRAY(except)->len; i++) {
                GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
                if (FD_ISSET(fileno(fptr->f), ep)) {
                    rb_ary_push(list, rb_ary_entry(except, i));
                }
                else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), ep)) {
                    rb_ary_push(list, rb_ary_entry(except, i));
                }
            }
        }
    }

    return res;                 /* returns an empty array on interrupt */
}
            
sysopen(path, [mode, [perm]]) => fixnum click to toggle source

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

IO.sysopen("testfile")   #=> 3
 
               static VALUE
rb_io_s_sysopen(argc, argv)
    int argc;
    VALUE *argv;
{
    VALUE fname, vmode, perm;
    int flags, fd;
    unsigned int fmode;
    char *path;

    rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
    SafeStringValue(fname);

    if (NIL_P(vmode)) flags = O_RDONLY;
    else if (FIXNUM_P(vmode)) flags = FIX2INT(vmode);
    else {
        SafeStringValue(vmode);
        flags = rb_io_mode_modenum(RSTRING(vmode)->ptr);
    }
    if (NIL_P(perm)) fmode = 0666;
    else             fmode = NUM2UINT(perm);

    path = ALLOCA_N(char, strlen(RSTRING(fname)->ptr)+1);
    strcpy(path, RSTRING(fname)->ptr);
    fd = rb_sysopen(path, flags, fmode);
    return INT2NUM(fd);
}
            

Public Instance Methods

ios << obj => ios click to toggle source

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

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

produces:

Hello world!
 
               VALUE
rb_io_addstr(io, str)
    VALUE io, str;
{
    rb_io_write(io, str);
    return io;
}
            
binmode => ios click to toggle source

Puts ios into binary mode. This is useful only in MS-DOS/Windows environments. Once a stream is in binary mode, it cannot be reset to nonbinary mode.

 
               VALUE
rb_io_binmode(io)
    VALUE io;
{
#if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
    OpenFile *fptr;

    GetOpenFile(io, fptr);
#ifdef __human68k__
    if (fptr->f)
        fmode(fptr->f, _IOBIN);
    if (fptr->f2)
        fmode(fptr->f2, _IOBIN);
#else
    if (fptr->f && setmode(fileno(fptr->f), O_BINARY) == -1)
        rb_sys_fail(fptr->path);
    if (fptr->f2 && setmode(fileno(fptr->f2), O_BINARY) == -1)
        rb_sys_fail(fptr->path);
#endif

    fptr->mode |= FMODE_BINMODE;
#endif
    return io;
}
            
close => nil click to toggle source

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

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

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

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

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

produces:

prog.rb:3:in `readlines': not opened for reading (IOError)
 from prog.rb:3
 
               static VALUE
rb_io_close_read(io)
    VALUE io;
{
    OpenFile *fptr;
    int n;

    if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
        rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    GetOpenFile(io, fptr);
    if (fptr->f2 == 0 && (fptr->mode & FMODE_WRITABLE)) {
        rb_raise(rb_eIOError, "closing non-duplex IO for reading");
    }
    if (fptr->f2 == 0) {
        return rb_io_close(io);
    }
    n = fclose(fptr->f);
    fptr->mode &= ~FMODE_READABLE;
    fptr->f = fptr->f2;
    fptr->f2 = 0;
    if (n != 0) rb_sys_fail(fptr->path);

    return Qnil;
}
            
close_write => nil click to toggle source

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

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

produces:

prog.rb:3:in `write': not opened for writing (IOError)
 from prog.rb:3:in `print'
 from prog.rb:3
 
               static VALUE
rb_io_close_write(io)
    VALUE io;
{
    OpenFile *fptr;
    int n;

    if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
        rb_raise(rb_eSecurityError, "Insecure: can't close");
    }
    GetOpenFile(io, fptr);
    if (fptr->f2 == 0 && (fptr->mode & FMODE_READABLE)) {
        rb_raise(rb_eIOError, "closing non-duplex IO for writing");
    }
    if (fptr->f2 == 0) {
        return rb_io_close(io);
    }
    n = fclose(fptr->f2);
    fptr->f2 = 0;
    fptr->mode &= ~FMODE_WRITABLE;
    if (n != 0) rb_sys_fail(fptr->path);

    return Qnil;
}
            
closed? => true or false click to toggle source

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

f = File.new("testfile")
f.close         #=> nil
f.closed?       #=> true
f = IO.popen("/bin/sh","r+")
f.close_write   #=> nil
f.closed?       #=> false
f.close_read    #=> nil
f.closed?       #=> true
 
               static VALUE
rb_io_closed(io)
    VALUE io;
{
    OpenFile *fptr;

    fptr = RFILE(io)->fptr;
    rb_io_check_initialized(fptr);
    return (fptr->f || fptr->f2)?Qfalse:Qtrue;
}
            
each(sep_string=$/) {|line| block } => ios click to toggle source
each_line(sep_string=$/) {|line| block } => ios

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

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...
 
               static VALUE
rb_io_each_line(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE str;
    VALUE rs;

    if (argc == 0) {
        rs = rb_rs;
    }
    else {
        rb_scan_args(argc, argv, "1", &rs);
        if (!NIL_P(rs)) StringValue(rs);
    }
    while (!NIL_P(str = rb_io_getline(rs, io))) {
        rb_yield(str);
    }
    return io;
}
            
each_byte {|byte| block } => nil click to toggle source

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.

f = File.new("testfile")
checksum = 0
f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
checksum                           #=> 12
 
               static VALUE
rb_io_each_byte(io)
    VALUE io;
{
    OpenFile *fptr;
    FILE *f;
    int c;

    GetOpenFile(io, fptr);

    for (;;) {
        rb_io_check_readable(fptr);
        f = fptr->f;
        READ_CHECK(f);
        clearerr(f);
        TRAP_BEG;
        c = getc(f);
        TRAP_END;
        if (c == EOF) {
            if (ferror(f)) {
                clearerr(f);
                if (!rb_io_wait_readable(fileno(f)))
                    rb_sys_fail(fptr->path);
                continue;
            }
            break;
        }
        rb_yield(INT2FIX(c & 0xff));
    }
    if (ferror(f)) rb_sys_fail(fptr->path);
    return io;
}
            
each_line(sep_string=$/) {|line| block } => ios click to toggle source

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

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...
 
               static VALUE
rb_io_each_line(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE str;
    VALUE rs;

    if (argc == 0) {
        rs = rb_rs;
    }
    else {
        rb_scan_args(argc, argv, "1", &rs);
        if (!NIL_P(rs)) StringValue(rs);
    }
    while (!NIL_P(str = rb_io_getline(rs, io))) {
        rb_yield(str);
    }
    return io;
}
            
eof => true or false click to toggle source
eof? => true or false

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 a input buffer. So IO#sysread doesn't work with IO#eof?.

 
               VALUE
rb_io_eof(io)
    VALUE io;
{
    OpenFile *fptr;
    int ch;

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

    if (feof(fptr->f)) return Qtrue;
    if (READ_DATA_PENDING(fptr->f)) return Qfalse;
    READ_CHECK(fptr->f);
    clearerr(fptr->f);
    TRAP_BEG;
    ch = getc(fptr->f);
    TRAP_END;

    if (ch != EOF) {
        ungetc(ch, fptr->f);
        return Qfalse;
    }
    rb_io_check_closed(fptr);
    clearerr(fptr->f);
    return Qtrue;
}
            
eof? => true or false click to toggle source

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 a input buffer. So IO#sysread doesn't work with IO#eof?.

 
               VALUE
rb_io_eof(io)
    VALUE io;
{
    OpenFile *fptr;
    int ch;

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

    if (feof(fptr->f)) return Qtrue;
    if (READ_DATA_PENDING(fptr->f)) return Qfalse;
    READ_CHECK(fptr->f);
    clearerr(fptr->f);
    TRAP_BEG;
    ch = getc(fptr->f);
    TRAP_END;

    if (ch != EOF) {
        ungetc(ch, fptr->f);
        return Qfalse;
    }
    rb_io_check_closed(fptr);
    clearerr(fptr->f);
    return Qtrue;
}
            
fcntl(integer_cmd, arg) => integer click to toggle source

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

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

    rb_scan_args(argc, argv, "11", &req, &arg);
    return rb_io_ctl(io, req, arg, 0);
#else
    rb_notimplement();
    return Qnil;                /* not reached */
#endif
}
            
fileno => fixnum click to toggle source
to_i => fixnum

Returns an integer representing the numeric file descriptor for ios.

$stdin.fileno    #=> 0
$stdout.fileno   #=> 1
 
               static VALUE
rb_io_fileno(io)
    VALUE io;
{
    OpenFile *fptr;
    int fd;

    GetOpenFile(io, fptr);
    fd = fileno(fptr->f);
    return INT2FIX(fd);
}
            
Also aliased as: to_i
flush => ios click to toggle source

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
 
               static VALUE
rb_io_flush(io)
    VALUE io;
{
    OpenFile *fptr;
    FILE *f;

    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);
    f = GetWriteFile(fptr);

    io_fflush(f, fptr);
#ifdef _WIN32
    fsync(fileno(f));
#endif
    return io;
}
            
fsync => 0 or nil click to toggle source

Immediately writes all buffered data in ios to disk. Returns nil if the underlying operating system does not support fsync(2). 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.

 
               static VALUE
rb_io_fsync(io)
    VALUE io;
{
#ifdef HAVE_FSYNC
    OpenFile *fptr;
    FILE *f;

    GetOpenFile(io, fptr);
    f = GetWriteFile(fptr);

    io_fflush(f, fptr);
    if (fsync(fileno(f)) < 0)
        rb_sys_fail(fptr->path);
    return INT2FIX(0);
#else
    rb_notimplement();
    return Qnil;                /* not reached */
#endif
}
            
getc => fixnum or nil click to toggle source

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

f = File.new("testfile")
f.getc   #=> 84
f.getc   #=> 104
 
               VALUE
rb_io_getc(io)
    VALUE io;
{
    OpenFile *fptr;
    FILE *f;
    int c;

    GetOpenFile(io, fptr);
    rb_io_check_readable(fptr);
    f = fptr->f;

  retry:
    READ_CHECK(f);
    clearerr(f);
    TRAP_BEG;
    c = getc(f);
    TRAP_END;

    if (c == EOF) {
        if (ferror(f)) {
            clearerr(f);
            if (!rb_io_wait_readable(fileno(f)))
                rb_sys_fail(fptr->path);
            goto retry;
        }
        return Qnil;
    }
    return INT2FIX(c & 0xff);
}
            
gets(sep_string=$/) => string or nil click to toggle source

Reads the next “line'' from the I/O stream; lines are separated by sep_string. 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.

File.new("testfile").gets   #=> "This is line one\n"
$_                          #=> "This is line one\n"
 
               static VALUE
rb_io_gets_m(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE rs, str;

    if (argc == 0) {
        rs = rb_rs;
    }
    else {
        rb_scan_args(argc, argv, "1", &rs);
        if (!NIL_P(rs)) StringValue(rs);
    }
    str = rb_io_getline(rs, io);
    rb_lastline_set(str);

    return str;
}
            
inspect => string click to toggle source

Return a string describing this IO object.

 
               static VALUE
rb_io_inspect(obj)
    VALUE obj;
{
    OpenFile *fptr;
    char *buf, *cname, *st = "";
    long len;

    fptr = RFILE(rb_io_taint_check(obj))->fptr;
    if (!fptr || !fptr->path) return rb_any_to_s(obj);
    cname = rb_obj_classname(obj);
    len = strlen(cname) + strlen(fptr->path) + 5;
    if (!(fptr->f || fptr->f2)) {
        st = " (closed)";
        len += 9;
    }
    buf = ALLOCA_N(char, len);
    snprintf(buf, len, "#<%s:%s%s>", cname, fptr->path, st);
    return rb_str_new2(buf);
}
            
ioctl(integer_cmd, arg) => integer click to toggle source

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

 
               static VALUE
rb_io_ioctl(argc, argv, io)
    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);
}
            
isatty => true or false click to toggle source

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

File.new("testfile").isatty   #=> false
File.new("/dev/tty").isatty   #=> true
 
               static VALUE
rb_io_isatty(io)
    VALUE io;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    if (isatty(fileno(fptr->f)) == 0)
        return Qfalse;
    return Qtrue;
}
            
lineno => integer click to toggle source

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

f = File.new("testfile")
f.lineno   #=> 0
f.gets     #=> "This is line one\n"
f.lineno   #=> 1
f.gets     #=> "This is line two\n"
f.lineno   #=> 2
 
               static VALUE
rb_io_lineno(io)
    VALUE io;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_readable(fptr);
    return INT2NUM(fptr->lineno);
}
            
lineno = integer => integer click to toggle source

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

f = File.new("testfile")
f.gets                     #=> "This is line one\n"
$.                         #=> 1
f.lineno = 1000
f.lineno                   #=> 1000
$. # lineno of last read   #=> 1
f.gets                     #=> "This is line two\n"
$. # lineno of last read   #=> 1001
 
               static VALUE
rb_io_set_lineno(io, lineno)
    VALUE io, lineno;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_readable(fptr);
    fptr->lineno = NUM2INT(lineno);
    return lineno;
}
            
pid => fixnum click to toggle source

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
 
               static VALUE
rb_io_pid(io)
    VALUE io;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    if (!fptr->pid)
        return Qnil;
    return INT2FIX(fptr->pid);
}
            
pos => integer click to toggle source

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
 
               static VALUE
rb_io_tell(io)
     VALUE io;
{
    OpenFile *fptr;
    off_t pos;

    GetOpenFile(io, fptr);
    pos = io_tell(fptr);
    if (pos < 0 && errno) rb_sys_fail(fptr->path);
    return OFFT2NUM(pos);
}
            
pos = integer => integer click to toggle source

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

f = File.new("testfile")
f.pos = 17
f.gets   #=> "This is line two\n"
 
               static VALUE
rb_io_set_pos(io, offset)
     VALUE io, offset;
{
    OpenFile *fptr;
    off_t pos;

    pos = NUM2OFFT(offset);
    GetOpenFile(io, fptr);
    pos = io_seek(fptr, pos, SEEK_SET);
    if (pos != 0) rb_sys_fail(fptr->path);
    clearerr(fptr->f);

    return OFFT2NUM(pos);
}
            
printf(format_string [, obj, ...] ) => nil click to toggle source

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

 
               VALUE
rb_io_printf(argc, argv, out)
    int argc;
    VALUE argv[];
    VALUE out;
{
    rb_io_write(out, rb_f_sprintf(argc, argv));
    return Qnil;
}
            
putc(obj) => obj click to toggle source

If obj is Numeric, write the character whose code is obj, otherwise write the first character of the string representation of obj to ios.

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

produces:

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

    rb_io_write(io, rb_str_new(&c, 1));
    return ch;
}
            
puts(obj, ...) => nil click to toggle source

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
 
               VALUE
rb_io_puts(argc, argv, out)
    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 (NIL_P(argv[i])) {
            line = rb_str_new2("nil");
        }
        else {
            line = rb_check_array_type(argv[i]);
            if (!NIL_P(line)) {
                rb_protect_inspect(io_puts_ary, line, out);
                continue;
            }
            line = rb_obj_as_string(argv[i]);
        }
        rb_io_write(out, line);
        if (RSTRING(line)->len == 0 ||
            RSTRING(line)->ptr[RSTRING(line)->len-1] != '\n') {
            rb_io_write(out, rb_default_rs);
        }
    }

    return Qnil;
}
            
read([length [, buffer]]) => string, buffer, or nil click to toggle source

Reads at most length bytes from the I/O stream, or to the end of file if length is omitted or is nil. length must be a non-negative integer or nil. 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"
 
               static VALUE
io_read(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    OpenFile *fptr;
    long n, len;
    VALUE length, str;

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

    if (NIL_P(length)) {
        if (!NIL_P(str)) StringValue(str);
        GetOpenFile(io, fptr);
        rb_io_check_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);
    }

    if (NIL_P(str)) {
        str = rb_tainted_str_new(0, len);
    }
    else {
        StringValue(str);
        rb_str_modify(str);
        rb_str_resize(str,len);
    }

    GetOpenFile(io, fptr);
    rb_io_check_readable(fptr);
    if (feof(fptr->f)) return Qnil;
    if (len == 0) return str;

    rb_str_locktmp(str);
    READ_CHECK(fptr->f);
    if (RSTRING(str)->len != len) {
        rb_raise(rb_eRuntimeError, "buffer string modified");
    }
    n = io_fread(RSTRING(str)->ptr, len, fptr);
    rb_str_unlocktmp(str);
    if (n == 0) {
        if (!fptr->f) return Qnil;
        if (feof(fptr->f)) {
            rb_str_resize(str, 0);
            return Qnil;
        }
        if (len > 0) rb_sys_fail(fptr->path);
    }
    rb_str_resize(str, n);
    RSTRING(str)->len = n;
    RSTRING(str)->ptr[n] = '\0';
    OBJ_TAINT(str);

    return str;
}
            
read_nonblock(maxlen) => string click to toggle source
read_nonblock(maxlen, outbuf) => outbuf

Reads at most maxlen bytes from ios using 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 read(2). It causes all errors read(2) causes: EAGAIN, EINTR, etc. The caller should care such errors.

#read_nonblock causes EOFError on EOF.

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

 
               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;
}
            
readchar => fixnum click to toggle source

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

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

    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}
            
readline(sep_string=$/) => string click to toggle source

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

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

    if (NIL_P(line)) {
        rb_eof_error();
    }
    return line;
}
            
readlines(sep_string=$/) => array click to toggle source

Reads all of the lines in ios, and returns them in anArray. Lines are separated by the optional sep_string. If sep_string is nil, the rest of the stream is returned as a single record. 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"
 
               static VALUE
rb_io_readlines(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE line, ary;
    VALUE rs;

    if (argc == 0) {
        rs = rb_rs;
    }
    else {
        rb_scan_args(argc, argv, "1", &rs);
        if (!NIL_P(rs)) StringValue(rs);
    }
    ary = rb_ary_new();
    while (!NIL_P(line = rb_io_getline(rs, io))) {
        rb_ary_push(ary, line);
    }
    return ary;
}
            
readpartial(maxlen) => string click to toggle source
readpartial(maxlen, outbuf) => 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 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 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 buffer is not empty, read from the buffer instead of “sysread for buffered IO (IOError)”.

  • It doesn't cause Errno::EAGAIN and Errno::EINTR. When readpartial meets EAGAIN 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 #sysread causes Errno::EAGAIN 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;
}
            
reopen(other_IO) => ios click to toggle source
reopen(path, mode_str) => ios

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

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(argc, argv, file)
    int argc;
    VALUE *argv;
    VALUE file;
{
    VALUE fname, nmode;
    char *mode;
    OpenFile *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);
        }
    }

    SafeStringValue(fname);
    rb_io_taint_check(file);
    fptr = RFILE(file)->fptr;
    if (!fptr) {
        fptr = RFILE(file)->fptr = ALLOC(OpenFile);
        MEMZERO(fptr, OpenFile, 1);
    }

    if (!NIL_P(nmode)) {
        fptr->mode = rb_io_mode_flags(StringValueCStr(nmode));
    }

    if (fptr->path) {
        free(fptr->path);
        fptr->path = 0;
    }

    fptr->path = strdup(StringValueCStr(fname));
    mode = rb_io_flags_mode(fptr->mode);
    if (!fptr->f) {
        fptr->f = rb_fopen(fptr->path, mode);
        if (fptr->f2) {
            fclose(fptr->f2);
            fptr->f2 = 0;
        }
        return file;
    }

    if (freopen(fptr->path, mode, fptr->f) == 0) {
        rb_sys_fail(fptr->path);
    }
#ifdef USE_SETVBUF
    if (setvbuf(fptr->f, NULL, _IOFBF, 0) != 0)
        rb_warn("setvbuf() can't be honoured for %s", fptr->path);
#endif

    if (fptr->f2) {
        if (freopen(fptr->path, "w", fptr->f2) == 0) {
            rb_sys_fail(fptr->path);
        }
    }

    return file;
}
            
rewind => 0 click to toggle source

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"
 
               static VALUE
rb_io_rewind(io)
    VALUE io;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    if (io_seek(fptr, 0L, 0) != 0) rb_sys_fail(fptr->path);
    clearerr(fptr->f);
    if (io == current_file) {
        gets_lineno -= fptr->lineno;
    }
    fptr->lineno = 0;

    return INT2FIX(0);
}
            
seek(amount, whence=SEEK_SET) → 0 click to toggle source

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"
 
               static VALUE
rb_io_seek_m(argc, argv, io)
    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);
}
            
stat => stat click to toggle source

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

f = File.new("testfile")
s = f.stat
"%o" % s.mode   #=> "100644"
s.blksize       #=> 4096
s.atime         #=> Wed Apr 09 08:53:54 CDT 2003
 
               static VALUE
rb_io_stat(obj)
    VALUE obj;
{
    OpenFile *fptr;
    struct stat st;

    GetOpenFile(obj, fptr);
    if (fstat(fileno(fptr->f), &st) == -1) {
        rb_sys_fail(fptr->path);
    }
    return stat_new(&st);
}
            
sync => true or false click to toggle source

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
 
               static VALUE
rb_io_sync(io)
    VALUE io;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
}
            
sync = boolean => boolean click to toggle source

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)

 
               static VALUE
rb_io_set_sync(io, mode)
    VALUE io, mode;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    if (RTEST(mode)) {
        fptr->mode |= FMODE_SYNC;
    }
    else {
        fptr->mode &= ~FMODE_SYNC;
    }
    return mode;
}
            
sysread(integer ) => string click to toggle source

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. Raises SystemCallError on error and EOFError at end of file.

f = File.new("testfile")
f.sysread(16)   #=> "This is line one"
 
               static VALUE
rb_io_sysread(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE len, str;
    OpenFile *fptr;
    long n, ilen;

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

    if (NIL_P(str)) {
        str = rb_str_new(0, ilen);
    }
    else {
        StringValue(str);
        rb_str_modify(str);
        rb_str_resize(str, ilen);
    }
    if (ilen == 0) return str;

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

    if (READ_DATA_BUFFERED(fptr->f)) {
        rb_raise(rb_eIOError, "sysread for buffered IO");
    }
    rb_str_locktmp(str);

    n = fileno(fptr->f);
    rb_thread_wait_fd(fileno(fptr->f));
    rb_io_check_closed(fptr);
    if (RSTRING(str)->len != ilen) {
        rb_raise(rb_eRuntimeError, "buffer string modified");
    }
    TRAP_BEG;
    n = read(fileno(fptr->f), RSTRING(str)->ptr, ilen);
    TRAP_END;

    rb_str_unlocktmp(str);
    if (n == -1) {
        rb_sys_fail(fptr->path);
    }
    rb_str_resize(str, n);
    if (n == 0 && ilen > 0) {
        rb_eof_error();
    }
    RSTRING(str)->len = n;
    RSTRING(str)->ptr[n] = '\0';
    OBJ_TAINT(str);

    return str;
}
            
sysseek(offset, whence=SEEK_SET) => integer click to toggle source

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

f = File.new("testfile")
f.sysseek(-13, IO::SEEK_END)   #=> 53
f.sysread(10)                  #=> "And so on."
 
               static VALUE
rb_io_sysseek(argc, argv, io)
    int argc;
    VALUE *argv;
    VALUE io;
{
    VALUE offset, ptrname;
    int whence = SEEK_SET;
    OpenFile *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->f)) {
        rb_raise(rb_eIOError, "sysseek for buffered IO");
    }
    if ((fptr->mode & FMODE_WRITABLE) && (fptr->mode & FMODE_WBUF)) {
        rb_warn("sysseek for buffered IO");
    }
    pos = lseek(fileno(fptr->f), pos, whence);
    if (pos == -1) rb_sys_fail(fptr->path);
    clearerr(fptr->f);

    return OFFT2NUM(pos);
}
            
syswrite(string) => integer click to toggle source

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

f = File.new("out", "w")
f.syswrite("ABCDEF")   #=> 6
 
               static VALUE
rb_io_syswrite(io, str)
    VALUE io, str;
{
    OpenFile *fptr;
    FILE *f;
    long n;

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

    GetOpenFile(io, fptr);
    rb_io_check_writable(fptr);
    f = GetWriteFile(fptr);

    if (fptr->mode & FMODE_WBUF) {
        rb_warn("syswrite for buffered IO");
    }
    if (!rb_thread_fd_writable(fileno(f))) {
        rb_io_check_closed(fptr);
    }
    TRAP_BEG;
    n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len);
    TRAP_END;

    if (n == -1) rb_sys_fail(fptr->path);

    return LONG2FIX(n);
}
            
tell => integer click to toggle source

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
 
               static VALUE
rb_io_tell(io)
     VALUE io;
{
    OpenFile *fptr;
    off_t pos;

    GetOpenFile(io, fptr);
    pos = io_tell(fptr);
    if (pos < 0 && errno) rb_sys_fail(fptr->path);
    return OFFT2NUM(pos);
}
            
to_i() click to toggle source
Alias for: fileno
to_io → ios click to toggle source

Returns ios.

 
               static VALUE
rb_io_to_io(io)
    VALUE io;
{
    return io;
}
            
tty? => true or false click to toggle source

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

File.new("testfile").isatty   #=> false
File.new("/dev/tty").isatty   #=> true
 
               static VALUE
rb_io_isatty(io)
    VALUE io;
{
    OpenFile *fptr;

    GetOpenFile(io, fptr);
    if (isatty(fileno(fptr->f)) == 0)
        return Qfalse;
    return Qtrue;
}
            
ungetc(integer) => nil click to toggle source

Pushes back one character (passed as a parameter) onto ios, such that a subsequent buffered 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                 #=> 84
f.ungetc(c)                #=> nil
f.getc                     #=> 84
 
               VALUE
rb_io_ungetc(io, c)
    VALUE io, c;
{
    OpenFile *fptr;
    int cc = NUM2INT(c);

    GetOpenFile(io, fptr);
    if (!(fptr->mode & FMODE_RBUF))
        rb_raise(rb_eIOError, "unread stream");
    rb_io_check_readable(fptr);

    if (ungetc(cc, fptr->f) == EOF && cc != EOF) {
        rb_raise(rb_eIOError, "ungetc failed");
    }
    return Qnil;
}
            
write(string) => integer click to toggle source

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
 
               static VALUE
io_write(io, str)
    VALUE io, str;
{
    OpenFile *fptr;
    long n;

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

    if (TYPE(io) != T_FILE) {
        /* port is not IO, call write method for it. */
        return rb_funcall(io, id_write, 1, str);
    }
    if (RSTRING(str)->len == 0) return INT2FIX(0);

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

    n = io_fwrite(str, fptr);
    if (n == -1L) rb_sys_fail(fptr->path);
    if (!(fptr->mode & FMODE_SYNC)) {
        fptr->mode |= FMODE_WBUF;
    }

    return LONG2FIX(n);
}
            
write_nonblock(string) => integer click to toggle source

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

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

 
               static VALUE
rb_io_write_nonblock(VALUE io, VALUE str)
{
    OpenFile *fptr;
    FILE *f;
    long n;

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

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

    f = GetWriteFile(fptr);

    rb_io_set_nonblock(fptr);
    n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len);

    if (n == -1) rb_sys_fail(fptr->path);

    return LONG2FIX(n);
}