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.
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 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); }
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.
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); }
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
.
numeric file descriptor
file mode. a string or an integer
hash for specifiying mode by name.
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.
opt
can have the following keys
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 “b” in argument mode
.
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.
a = IO.new(2,"w") # '2' is standard error $stderr.puts "Hello" a.puts "World"
produces:
Hello World
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); }
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; }
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); }
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 mode.
# set IO encoding nkf_io = IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") euc_jp_string = nkf_io.read # discard standard error using spawn option. # See the document of Kernel.spawn. ls_io = IO.popen(["ls", "/", :err=>"/dev/null"]) 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 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 $? 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 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)> <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)) { tmp = rb_ary_dup(tmp); RBASIC(tmp)->klass = 0; port = pipe_open_v(RARRAY_LEN(tmp), 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; }
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 "
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)) { rb_io_binmode(arg.io); rb_io_seek(arg.io, offset, SEEK_SET); if (arg.argc == 2) arg.argc = 1; } return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io); }
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.
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); }
See Kernel#select
.
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 < sizeof(args.fdsets) / sizeof(args.fdsets[0]); ++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 }
Opens the given path, returning the underlying file descriptor as a
Fixnum
.
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; char *path; 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); path = RSTRING_PTR(fname); fd = rb_sysopen(path, oflags, perm); return INT2NUM(fd); }
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>
static VALUE rb_io_s_try_convert(VALUE dummy, VALUE io) { return rb_io_check_io(io); }
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(VALUE io, VALUE str) { rb_io_write(io, str); return io; }
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
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; }
Returns true
if ios is binmode.
static VALUE rb_io_binmode_p(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse; }
Returns an enumerator that gives each byte (0..255) in ios. The
stream must be opened for reading or an IOError
will be
raised.
f = File.new("testfile") f.bytes.to_a #=> [104, 101, 108, 108, 111] f.rewind f.bytes.sort #=> [101, 104, 108, 108, 111]
static VALUE rb_io_bytes(VALUE io) { return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0); }
Returns an enumerator that gives each character in ios. The stream
must be opened for reading or an IOError
will be raised.
f = File.new("testfile") f.chars.to_a #=> ["h", "e", "l", "l", "o"] f.rewind f.chars.sort #=> ["e", "h", "l", "l", "o"]
static VALUE rb_io_chars(VALUE io) { return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0); }
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(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; }
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) { #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) 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); } } #else rb_notimplement(); #endif return Qnil; }
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
static VALUE rb_io_close_on_exec_p(VALUE io) { #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC) 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; #else rb_notimplement(); return Qnil; /* not reached */ #endif }
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(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, Qfalse); 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); }
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(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; }
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(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; }
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.
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(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; }
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(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_readable(fptr); READ_CHECK(fptr); if (io_fillbuf(fptr) < 0) { break; } } return io; }
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.
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_readable(fptr); enc = io_input_encoding(fptr); READ_CHECK(fptr); while (!NIL_P(c = io_getc(fptr, enc))) { rb_yield(c); } return io; }
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.
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(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; }
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(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); rb_io_check_readable(fptr); if (READ_DATA_PENDING(fptr)) return Qfalse; READ_CHECK(fptr); if (io_fillbuf(fptr) < 0) { return Qtrue; } return Qfalse; }
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(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); rb_io_check_readable(fptr); if (READ_DATA_PENDING(fptr)) return Qfalse; READ_CHECK(fptr); if (io_fillbuf(fptr) < 0) { return Qtrue; } return Qfalse; }
Returns the Encoding object that represents the
encoding of the file. If io is write mode and no encoding is specified,
returns nil
.
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)); }
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(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 }
Returns an integer representing the numeric file descriptor for ios.
$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); }
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
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; }
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(VALUE io) { #ifdef HAVE_FSYNC 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); #else rb_notimplement(); return Qnil; /* not reached */ #endif }
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
VALUE rb_io_getbyte(VALUE io) { rb_io_t *fptr; int c; GetOpenFile(io, fptr); rb_io_check_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); }
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"
static VALUE rb_io_getc(VALUE io) { rb_io_t *fptr; rb_encoding *enc; GetOpenFile(io, fptr); rb_io_check_readable(fptr); enc = io_input_encoding(fptr); READ_CHECK(fptr); return io_getc(fptr, enc); }
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"
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; }
Return a string describing this IO object.
static VALUE rb_io_inspect(VALUE obj) { rb_io_t *fptr; const char *cname; const char *st = ""; fptr = RFILE(rb_io_taint_check(obj))->fptr; if (!fptr || NIL_P(fptr->pathv)) return rb_any_to_s(obj); cname = rb_obj_classname(obj); if (fptr->fd < 0) { st = " (closed)"; } return rb_sprintf("#<%s:%s%s>", cname, RSTRING_PTR(fptr->pathv), st); }
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)); }
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(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); }
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(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); if (isatty(fptr->fd) == 0) return Qfalse; return Qtrue; }
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(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); rb_io_check_readable(fptr); return INT2NUM(fptr->lineno); }
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
static VALUE rb_io_set_lineno(VALUE io, VALUE lineno) { rb_io_t *fptr; GetOpenFile(io, fptr); rb_io_check_readable(fptr); fptr->lineno = NUM2INT(lineno); return lineno; }
Returns an enumerator that gives each line in ios. The stream must
be opened for reading or an IOError
will be raised.
f = File.new("testfile") f.lines.to_a #=> ["foo\n", "bar\n"] f.rewind f.lines.sort #=> ["bar\n", "foo\n"]
static VALUE rb_io_lines(int argc, VALUE *argv, VALUE io) { return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv); }
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(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); if (!fptr->pid) return Qnil; return PIDT2NUM(fptr->pid); }
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(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); return OFFT2NUM(pos); }
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(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) 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 record separator ($\
) is not
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.
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++) { rb_io_write(out, argv[i]); if (!NIL_P(rb_output_fs)) { rb_io_write(out, rb_output_fs); } } if (argc > 0 && !NIL_P(rb_output_rs)) { rb_io_write(out, rb_output_rs); } return Qnil; }
Formats and writes to ios, converting parameters under control of
the format string. See Kernel#sprintf
for details.
VALUE rb_io_printf(int argc, VALUE *argv, VALUE out) { rb_io_write(out, rb_f_sprintf(argc, argv)); return Qnil; }
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(VALUE io, VALUE ch) { char c = NUM2CHR(ch); rb_io_write(io, rb_str_new(&c, 1)); return ch; }
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(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++) { 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]); rb_io_write(out, line); if (RSTRING_LEN(line) == 0 || RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') { rb_io_write(out, rb_default_rs); } } return Qnil; }
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.
ios.read(0)
returns ""
.
f = File.new("testfile") f.read(16) #=> "This is line one"
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)) { 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_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 (len == 0) return str; READ_CHECK(fptr); if (RSTRING_LEN(str) != len) { rb_raise(rb_eRuntimeError, "buffer string modified"); } 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; }
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.
#read_nonblock causes EOFError on EOF.
If the read 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 EWOULDBLOCK, #read_nonblock should not be called until io is readable for avoiding busy loop. This can be done as follows.
begin result = io.read_nonblock(maxlen) rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR IO.select([io]) retry end
Note that this 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; }
Reads a byte as with IO#getbyte
, but raises an
EOFError
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; }
Reads a one-character string from ios. Raises an
EOFError
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; }
Reads a line as with IO#gets
, but raises an
EOFError
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; }
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"
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; }
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::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 #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; }
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(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(RSTRING_PTR(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(RSTRING_PTR(fptr->pathv), oflags, 0666); } return file; }
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(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); if (io_seek(fptr, 0L, 0) < 0) 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); }
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(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); }
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; 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; }
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(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); }
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(VALUE io) { rb_io_t *fptr; io = GetWriteIO(io); GetOpenFile(io, fptr); return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse; }
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(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; }
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"
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); 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)) { rb_raise(rb_eIOError, "sysread for buffered IO"); } n = fptr->fd; rb_thread_wait_fd(fptr->fd); rb_io_check_closed(fptr); if (RSTRING_LEN(str) != ilen) { rb_raise(rb_eRuntimeError, "buffer string modified"); } n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen); 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; }
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(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)) { rb_raise(rb_eIOError, "sysseek for buffered IO"); } if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) { rb_warn("sysseek for buffered IO"); } pos = lseek(fptr->fd, pos, whence); if (pos == -1) rb_sys_fail_path(fptr->pathv); return OFFT2NUM(pos); }
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(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); }
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(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); return OFFT2NUM(pos); }
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(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr); if (isatty(fptr->fd) == 0) return Qfalse; return Qtrue; }
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
VALUE rb_io_ungetbyte(VALUE io, VALUE b) { rb_io_t *fptr; GetOpenFile(io, fptr); rb_io_check_readable(fptr); io_unset_eof(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; }
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 #=> "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_readable(fptr); io_unset_eof(fptr); if (NIL_P(c)) return Qnil; if (FIXNUM_P(c)) { int cc = FIX2INT(c); rb_encoding *enc = io_read_encoding(fptr); char buf[16]; c = rb_str_new(buf, rb_enc_mbcput(cc, buf, enc)); } else { SafeStringValue(c); } if (NEED_READCONV(fptr)) { len = RSTRING_LEN(c); make_readconv(fptr, 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 -= len; fptr->cbuf_len += len; MEMMOVE(fptr->cbuf+fptr->cbuf_off, RSTRING_PTR(c), char, len); } else { io_ungetbyte(c, fptr); } return Qnil; }
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_m(VALUE io, VALUE str) { return io_write(io, str, 0); }
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 write buffer is not empty, it is flushed at first.
When #write_nonblock raises EWOULDBLOCK, #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 Errno::EWOULDBLOCK, Errno::EAGAIN, 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.
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) rb_sys_fail_path(fptr->pathv); return LONG2FIX(n); }