Support for the Ruby 2.1 series ended on March 31 2017. See here for details.
The IO class is the basis for all input and output in Ruby. An I/O stream may be duplexed (that is, bidirectional), and so may use more than one native operating system stream.
Many of the examples in this section use the File class, the only standard subclass of IO. The two classes are closely associated. Like the File class, the Socket library subclasses from IO (such as TCPSocket or UDPSocket).
The Kernel#open method can create an IO (or File) object for these types of arguments:
A plain string represents a filename suitable for the underlying operating system.
A string starting with "|" indicates a subprocess.
The remainder of the string following the "|" is
invoked as a process with appropriate input/output channels connected to
it.
A string equal to "|-" will create another Ruby
instance as a subprocess.
The IO may be opened with different file modes (read-only, write-only) and encodings for proper conversion. See ::new for these options. See Kernel#open for details of the various command formats described above.
::popen, the Open3 library, or Process#spawn may also be used to communicate with subprocesses through an IO.
Ruby will convert pathnames between different operating system conventions
if possible. For instance, on a Windows system the filename
"/gumby/ruby/test.rb" will be opened as
"\gumby\ruby\test.rb". When specifying a
Windows-style filename in a Ruby string, remember to escape the
backslashes:
"c:\\gumby\\ruby\\test.rb"
Our examples here will use the Unix-style forward slashes; File::ALT_SEPARATOR can be used to get the platform-specific separator character.
The global constant ARGF (also accessible as $<) provides an IO-like stream which allows access to all files mentioned on the command line (or STDIN if no files are mentioned). ARGF#path and its alias ARGF#filename are provided to access the name of the file currently being read.
The io/console extension provides methods for interacting with the console. The console can be accessed from IO.console or the standard input/output/error IO objects.
Requiring io/console adds the following methods:
IO::console
IO#raw
IO#raw!
IO#cooked
IO#cooked!
IO#getch
IO#echo=
IO#echo?
IO#noecho
IO#winsize
IO#winsize=
IO#iflush
IO#ioflush
IO#oflush
Example:
require 'io/console' rows, columns = $stdin.winsize puts "Your screen is #{columns} wide and #{rows} tall"
Set I/O position from the current position
Set I/O position to the next location containing data
Set I/O position from the end
Set I/O position to the next hole
Set I/O position from the beginning
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 "
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);
}
Same as IO.write except opening the file in binary mode and
ASCII-8BIT encoding (“wb:ASCII-8BIT”).
static VALUE
rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
{
return io_s_write(argc, argv, 1);
}
::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_fd_init(&st.fds);
rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
return OFFT2NUM(st.total);
}
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;
}
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.
static VALUE
rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
{
VALUE opt;
int orig_argc = argc;
struct foreach_arg arg;
argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
RETURN_ENUMERATOR(self, orig_argc, argv);
open_key_args(argc, argv, opt, &arg);
if (NIL_P(arg.io)) return Qnil;
return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
}
Returns a new IO object (a stream) for the given
integer file descriptor fd and mode string.
opt may be used to specify parts of mode in a
more readable fashion. See also ::sysopen and ::for_fd.
::new is called by various File and IO opening methods such as ::open, Kernel#open, and File.open.
When mode is an integer it must be combination of the modes
defined in File::Constants
(File::RDONLY, +File::WRONLY | File::CREAT+). See the open(2)
man page for more information.
When mode is a string it must be in one of the following
forms:
fmode fmode ":" ext_enc fmode ":" ext_enc ":" int_enc fmode ":" "BOM|UTF-*"
fmode is an IO open mode string,
ext_enc is the external encoding for the IO and int_enc is the internal encoding.
Ruby allows the following open modes:
"r" Read-only, starts at beginning of file (default mode).
"r+" Read-write, starts at beginning of file.
"w" Write-only, truncates existing file
to zero length or creates a new file for writing.
"w+" Read-write, truncates existing file to zero length
or creates a new file for reading and writing.
"a" Write-only, 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.
The following modes must be used separately, and along with one or more of the modes seen above.
"b" Binary file mode
Suppresses EOL <-> CRLF conversion on Windows. And
sets external encoding to ASCII-8BIT unless explicitly
specified.
"t" Text file mode
When the open mode of original IO is read only, the mode cannot be changed to be writable. Similarly, the open mode cannot be changed from write only to readable.
When such a change is attempted the error is raised in different locations according to the platform.
When ext_enc is specified, strings read will be tagged by the
encoding when reading, and strings output will be converted to the
specified encoding when writing.
When ext_enc and int_enc are specified read
strings will be converted from ext_enc to int_enc
upon input, and written strings will be converted from int_enc
to ext_enc upon output. See Encoding for further details of transcoding on
input and output.
If “BOM|UTF-8”, “BOM|UTF-16LE” or “BOM|UTF16-BE” are used, ruby checks for
a Unicode BOM in the input document to help determine the encoding. For
UTF-16 encodings the file open mode must be binary. When present, the BOM
is stripped and the external encoding from the BOM is used. When the BOM
is missing the given Unicode encoding is used as ext_enc.
(The BOM-set encoding option is case insensitive, so “bom|utf-8” is also
valid.)
opt can be used instead of mode for improved
readability. The following keys are supported:
Same as mode parameter
External encoding for the IO. “-” is a synonym for the default external encoding.
Internal encoding for the IO. “-” is a synonym for the default internal encoding.
If the value is nil no conversion occurs.
Specifies external and internal encodings as “extern:intern”.
If the value is truth value, same as “t” in argument mode.
If the value is truth value, same as “b” in argument mode.
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.
fd = IO.sysopen("/dev/tty", "w") a = IO.new(fd,"w") $stderr.puts "Hello" a.puts "World"
Produces:
Hello World
require 'fcntl' fd = STDERR.fcntl(Fcntl::F_DUPFD) io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true) io.puts "Hello, World!" fd = STDERR.fcntl(Fcntl::F_DUPFD) io = IO.new(fd, mode: 'w', cr_newline: true, external_encoding: Encoding::UTF_16LE) io.puts "Hello, World!"
Both of above print “Hello, World!” in UTF-16LE to standard error output
with converting EOL generated by puts to CR.
static VALUE
rb_io_initialize(int argc, VALUE *argv, VALUE io)
{
VALUE fnum, vmode;
rb_io_t *fp;
int fd, fmode, oflags = O_RDONLY;
convconfig_t convconfig;
VALUE opt;
#if defined(HAVE_FCNTL) && defined(F_GETFL)
int ofmode;
#else
struct stat st;
#endif
argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
fd = NUM2INT(fnum);
if (rb_reserved_fd_p(fd)) {
rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
}
#if defined(HAVE_FCNTL) && defined(F_GETFL)
oflags = fcntl(fd, F_GETFL);
if (oflags == -1) rb_sys_fail(0);
#else
if (fstat(fd, &st) == -1) rb_sys_fail(0);
#endif
rb_update_max_fd(fd);
#if defined(HAVE_FCNTL) && defined(F_GETFL)
ofmode = rb_io_oflags_fmode(oflags);
if (NIL_P(vmode)) {
fmode = ofmode;
}
else if ((~ofmode & fmode) & FMODE_READWRITE) {
VALUE error = INT2FIX(EINVAL);
rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
}
#endif
if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
fmode |= FMODE_PREP;
}
MakeOpenFile(io, fp);
fp->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;
}
With no associated block, IO.open is a synonym for ::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, ::open
returns the value of the block.
See ::new for a description of the
fd, mode and opt parameters.
static VALUE
rb_io_s_open(int argc, VALUE *argv, VALUE klass)
{
VALUE io = rb_class_new_instance(argc, argv, klass);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, io, io_close, io);
}
return 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