Ruby 2.4

IO

class IO

Parent:ObjectIncluded modules:File::Constants, Enumerable

期望库加入IO实例方法,对tcl的期望扩展做类似的操作。

为了使用这种方法,你必须要求:

require 'expect'

请看使用期望。

IO类是Ruby中所有输入和输出的基础。I/O流可能是双工的(即双向的),因此可能会使用多个本地操作系统流。

本节中的许多示例都使用File类,这是IO的唯一标准子类。这两个班级密切相关。像File类一样,来自IO的Socket库子类(如TCPSocket或UDPSocket)。

Kernel#open方法可以为这些类型的参数创建一个IO(或File)对象:

  • 一个普通的字符串表示一个适合底层操作系统的文件名。

  • 一个以字符开始的字符串"|"表示一个子进程。跟在该字符串后面的字符串的其余部分"|"被调用为具有连接到它的相应输入/输出通道的进程。

  • 等于的字符串"|-"将创建另一个Ruby实例作为子进程.IO可以用不同的文件模式(只读,只写)和适当的转换编码打开。

  • ::console

  • #raw

  • #raw!

  • #cooked

  • #cooked!

  • #getch

  • #echo=

  • #echo?

  • #noecho

  • #winsize

  • #winsize=

  • #iflush

  • #ioflush

  • #oflush

  • 新行转换已禁用

  • 编码转换禁用

  • 内容被视为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; }

binmode? → true or false

如果ios是binmode,则返回true

static VALUE rb_io_binmode_p(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse; }

bytes()

这是一个不推荐的别名each_byte

static VALUE rb_io_bytes(VALUE io) { rb_warn("IO#bytes is deprecated; use #each_byte instead" if (!rb_block_given_p()) return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0 return rb_io_each_byte(io }

chars()

这是一个不推荐的别名each_char

static VALUE rb_io_chars(VALUE io) { rb_warn("IO#chars is deprecated; use #each_char instead" if (!rb_block_given_p()) return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0 return rb_io_each_char(io }

close → nil

关闭ios并刷新任何挂起的写入操作系统。该流不可用于任何进一步的数据操作; 一IOError,如果这样的尝试升高。I/O流在被垃圾回收器声明时会自动关闭。

如果ios被打开IO.popenclose设置$?

从Ruby 2.3开始,在封闭的IO对象上调用这个方法就被忽略了。

static VALUE rb_io_close_m(VALUE io) { rb_io_t *fptr = rb_io_get_fptr(io if (fptr->fd < 0) { return Qnil; } rb_io_close(io return Qnil; }

close_on_exec = bool → true or false

设置一个关闭执行标志。

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

从Ruby 2.0.0开始,Ruby默认设置所有文件描述符的close-on-exec标志。所以你不需要自己设定。另外,如果另一个线程使用fork()和exec()(例如通过system()方法),则取消设置close-on-exec标志可能导致文件描述符泄漏。如果您真的需要将文件描述符继承到子进程,请使用spawn()的参数,如fd => fd。

static VALUE rb_io_set_close_on_exec(VALUE io, VALUE arg) { int flag = RTEST(arg) ? FD_CLOEXEC : 0; rb_io_t *fptr; VALUE write_io; int fd, ret; write_io = GetWriteIO(io if (io != write_io) { GetOpenFile(write_io, fptr if (fptr && 0 <= (fd = fptr->fd)) { if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv if ((ret & FD_CLOEXEC) != flag) { ret = (ret & ~FD_CLOEXEC) | flag; ret = fcntl(fd, F_SETFD, ret if (ret == -1) rb_sys_fail_path(fptr->pathv } } } GetOpenFile(io, fptr if (fptr && 0 <= (fd = fptr->fd)) { if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv if ((ret & FD_CLOEXEC) != flag) { ret = (ret & ~FD_CLOEXEC) | flag; ret = fcntl(fd, F_SETFD, ret if (ret == -1) rb_sys_fail_path(fptr->pathv } } return Qnil; }

close_on_exec? → true or false

如果ios将在exec上关闭,则返回true

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

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

close_read → nil Show source

关闭duplex I/O流的读取端(即,包含读取和写入流的管道,例如管道)。IOError如果数据流不是双工的,会引发一次。

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; fptr = rb_io_get_fptr(rb_io_taint_check(io) if (fptr->fd < 0) return Qnil; 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; wfptr = rb_io_get_fptr(rb_io_taint_check(write_io) wfptr->pid = fptr->pid; fptr->pid = 0; RFILE(io)->fptr = wfptr; /* bind to write_io temporarily to get rid of memory/fd leak */ fptr->tied_io_for_writing = 0; RFILE(write_io)->fptr = fptr; rb_io_fptr_cleanup(fptr, FALSE /* should not finalize fptr because another thread may be reading it */ return Qnil; } if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) { rb_raise(rb_eIOError, "closing non-duplex IO for reading" } return rb_io_close(io }

close_write → nil Show source

关闭duplex I/O流的写入结束(即,包含读取和写入流的管道,例如管道)。IOError如果数据流不是双工的,会引发一次。

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; write_io = GetWriteIO(io fptr = rb_io_get_fptr(rb_io_taint_check(write_io) if (fptr->fd < 0) return Qnil; 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_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) { rb_raise(rb_eIOError, "closing non-duplex IO for writing" } if (io != write_io) { fptr = rb_io_get_fptr(rb_io_taint_check(io) fptr->tied_io_for_writing = 0; } rb_io_close(write_io return Qnil; }

closed? → true or false Show source

如果ios完全关闭(对于双向流,读写器),则返回true,否则返回false

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 = rb_io_get_fptr(io return 0 <= fptr->fd ? Qfalse : Qtrue; }

codepoints()

这是一个不推荐的别名each_codepoint

static VALUE rb_io_codepoints(VALUE io) { rb_warn("IO#codepoints is deprecated; use #each_codepoint instead" if (!rb_block_given_p()) return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0 return rb_io_each_codepoint(io }

cooked {|io| }

selfcooked模式下的产量。

STDIN.cooked(&:gets)

将读取并返回一行回显和行编辑。

您必须要求'io/console'才能使用此方法。

static VALUE console_cooked(VALUE io) { return ttymode(io, rb_yield, set_cookedmode, NULL }

cooked!

启用cooked模式。

如果终端模式需要返回,请使用io.cooked {...}。

您必须要求'io/console'才能使用此方法。

static VALUE console_set_cooked(VALUE io) { conmode t; rb_io_t *fptr; int fd; GetOpenFile(io, fptr fd = GetReadFD(fptr if (!getattr(fd, &t)) rb_sys_fail(0 set_cookedmode(&t, NULL if (!setattr(fd, &t)) rb_sys_fail(0 return io; }

cursor()

static VALUE console_cursor_pos(VALUE io) { rb_io_t *fptr; int fd; rb_console_size_t ws; GetOpenFile(io, fptr fd = GetWriteFD(fptr if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) { rb_syserr_fail(LAST_ERROR, 0 } return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.X), UINT2NUM(ws.dwCursorPosition.Y) }

cursor=(p1)

static VALUE console_cursor_set(VALUE io, VALUE cpos) { cpos = rb_convert_type(cpos, T_ARRAY, "Array", "to_ary" if (RARRAY_LEN(cpos) != 2) rb_raise(rb_eArgError, "expected 2D coordinate" return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1) }

each(sep=$/) {|line| block } → ios

each(limit) {|line| block } → ios

each(sep,limit) {|line| block } → ios

each(...) → an_enumerator

each_line(sep=$/) {|line| block } → ios

each_line(limit) {|line| block } → ios

each_line(sep,limit) {|line| block } → ios

each_line(...) → an_enumerator

ios中的每一行执行块,其中行由sep分隔。ios必须打开以供阅读或IOError将会被提出。

如果没有给出块,则返回一个枚举器。

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; struct getline_arg args; RETURN_ENUMERATOR(io, argc, argv prepare_getline_args(argc, argv, &args, io if (args.limit == 0) rb_raise(rb_eArgError, "invalid limit: 0 for each_line" while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) { rb_yield(str } return io; }

each_byte {|byte| block } → ios Show source

each_byte → an_enumerator

ios中的每个字节(0..255)调用给定的块一次,将该字节作为参数传递。该流必须打开阅读或IOError将被提出。

如果没有给出块,则返回一个枚举器。

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; RETURN_ENUMERATOR(io, 0, 0 GetOpenFile(io, fptr do { while (fptr->rbuf.len > 0) { char *p = fptr->rbuf.ptr + fptr->rbuf.off++; fptr->rbuf.len--; rb_yield(INT2FIX(*p & 0xff) errno = 0; } rb_io_check_byte_readable(fptr READ_CHECK(fptr } while (io_fillbuf(fptr) >= 0 return io; }

each_char {|c| block } → ios Show source

each_char → an_enumerator

ios中的每个字符调用一次给定的块,将该字符作为参数传递。该流必须打开阅读或IOError将被提出。

如果没有给出块,则返回一个枚举器。

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

static VALUE rb_io_each_char(VALUE io) { rb_io_t *fptr; rb_encoding *enc; VALUE c; RETURN_ENUMERATOR(io, 0, 0 GetOpenFile(io, fptr rb_io_check_char_readable(fptr enc = io_input_encoding(fptr READ_CHECK(fptr while (!NIL_P(c = io_getc(fptr, enc))) { rb_yield(c } return io; }

each_codepoint {|c| block } → ios Show source

codepoints {|c| block } → ios

each_codepoint → an_enumerator

codepoints → an_enumerator

传递iosInteger中每个字符的序号,将代码点作为参数传递。该流必须打开阅读或将被提出。IOError

如果没有给出块,则返回一个枚举器。

static VALUE rb_io_each_codepoint(VALUE io) { rb_io_t *fptr; rb_encoding *enc; unsigned int c; int r, n; RETURN_ENUMERATOR(io, 0, 0 GetOpenFile(io, fptr rb_io_check_char_readable(fptr READ_CHECK(fptr if (NEED_READCONV(fptr)) { SET_BINARY_MODE(fptr r = 1; /* no invalid char yet */ for (;;) { make_readconv(fptr, 0 for (;;) { if (fptr->cbuf.len) { if (fptr->encs.enc) r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len, fptr->encs.enc else r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1 if (!MBCLEN_NEEDMORE_P(r)) break; if (fptr->cbuf.len == fptr->cbuf.capa) { rb_raise(rb_eIOError, "too long character" } } if (more_char(fptr) == MORE_CHAR_FINISHED) { clear_readconv(fptr if (!MBCLEN_CHARFOUND_P(r)) { enc = fptr->encs.enc; goto invalid; } return io; } } if (MBCLEN_INVALID_P(r)) { enc = fptr->encs.enc; goto invalid; } n = MBCLEN_CHARFOUND_LEN(r if (fptr->encs.enc) { c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len, fptr->encs.enc } else { c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off]; } fptr->cbuf.off += n; fptr->cbuf.len -= n; rb_yield(UINT2NUM(c) } } NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr enc = io_input_encoding(fptr while (io_fillbuf(fptr) >= 0) { r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc if (MBCLEN_CHARFOUND_P(r) && (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) { c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc fptr->rbuf.off += n; fptr->rbuf.len -= n; rb_yield(UINT2NUM(c) } else if (MBCLEN_INVALID_P(r)) { invalid: rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc) } else if (MBCLEN_NEEDMORE_P(r)) { char cbuf[8], *p = cbuf; int more = MBCLEN_NEEDMORE_LEN(r if (more > numberof(cbuf)) goto invalid; more += n = fptr->rbuf.len; if (more > numberof(cbuf)) goto invalid; while ((n = (int)read_buffered_data(p, more, fptr)) > 0 && (p += n, (more -= n) > 0)) { if (io_fillbuf(fptr) < 0) goto invalid; if ((n = fptr->rbuf.len) > more) n = more; } r = rb_enc_precise_mbclen(cbuf, p, enc if (!MBCLEN_CHARFOUND_P(r)) goto invalid; c = rb_enc_codepoint(cbuf, p, enc rb_yield(UINT2NUM(c) } else { continue; } } return io; }

each_line(sep=$/) {|line| block } → ios

each_line(limit) {|line| block } → ios

each_line(sep,limit) {|line| block } → ios

each_line(...) → an_enumerator

ios中的每一行执行块,其中行由sep分隔。ios必须打开以供阅读或IOError将会被提出。

如果没有给出块,则返回一个枚举器。

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; struct getline_arg args; RETURN_ENUMERATOR(io, argc, argv prepare_getline_args(argc, argv, &args, io if (args.limit == 0) rb_raise(rb_eArgError, "invalid limit: 0 for each_line" while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) { rb_yield(str } return io; }

echo = flag Show source

启用/禁用回显。在某些平台上,此标志和原始/熟化模式的所有组合可能无效。

您必须要求'io / console'才能使用此方法。

static VALUE console_set_echo(VALUE io, VALUE f) { conmode t; rb_io_t *fptr; int fd; GetOpenFile(io, fptr fd = GetReadFD(fptr if (!getattr(fd, &t)) rb_sys_fail(0 if (RTEST(f)) set_echo(&t, NULL else set_noecho(&t, NULL if (!setattr(fd, &t)) rb_sys_fail(0 return io; }

echo? → true or false Show source

如果启用了回显,则返回true

您必须要求'io/console'才能使用此方法。

static VALUE console_echo_p(VALUE io) { conmode t; rb_io_t *fptr; int fd; GetOpenFile(io, fptr fd = GetReadFD(fptr if (!getattr(fd, &t)) rb_sys_fail(0 return echo_p(&t) ? Qtrue : Qfalse; }

eof → true or false

eof? → true or false

如果ios在文件末尾,表示没有更多数据要读取,则返回true 。该流必须打开阅读或IOError将被提出。

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

如果ios是诸如管道或套接字之类的流,则IO#eof?阻塞直到另一端发送一些数据或关闭它。

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

请注意,IO#eof?将数据读取到输入字节缓冲区。因此,除非您先调用(不适用于某些流),否则IO#sysread可能无法按照您的意愿行事。IO#eof?IO#rewind

VALUE rb_io_eof(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr rb_io_check_char_readable(fptr if (READ_CHAR_PENDING(fptr)) return Qfalse; if (READ_DATA_PENDING(fptr)) return Qfalse; READ_CHECK(fptr #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) { return eof(fptr->fd) ? Qtrue : Qfalse; } #endif if (io_fillbuf(fptr) < 0) { return Qtrue; } return Qfalse; }

eof? → true or false

如果ios在文件末尾,表示没有更多数据要读取,则返回true 。该流必须打开阅读或IOError将被提出。

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

如果ios是诸如管道或套接字之类的流,则IO#eof?阻塞直到另一端发送一些数据或关闭。

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

请注意,IO#eof?将数据读取到输入字节缓冲区。因此,除非您先调用IO#rewind(不适用于某些流),否则IO#sysread可能无法按照您IO#eof?的意愿行事。

VALUE rb_io_eof(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr rb_io_check_char_readable(fptr if (READ_CHAR_PENDING(fptr)) return Qfalse; if (READ_DATA_PENDING(fptr)) return Qfalse; READ_CHECK(fptr #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) { return eof(fptr->fd) ? Qtrue : Qfalse; } #endif if (io_fillbuf(fptr) < 0) { return Qtrue; } return Qfalse; }

IO#expect(pattern,timeout=9999999) → Array

IO#expect(pattern,timeout=9999999) { |result| ... } → nil

从IO中读取,直到给定的pattern匹配或timeout结束。

它返回一个带有读缓冲区的数组,然后是匹配。如果给出了一个块,结果将被输出到该块并返回nil。

在没有块的情况下调用时,它会一直等待,直到pattern从IO获得匹配给定的输入或者超时过后指定的时间。从IO获取模式时返回数组。数组的第一个元素是从IO中获得的整个字符串,直到模式匹配,然后是指示哪些模式与正则表达式中的锚点匹配的元素。

可选的超时参数以秒为单位定义等待模式的总时间。如果超时到期或找到eof,返回或放弃nil。但是,超时会话中的缓冲区将保留用于下一个期望调用。默认超时时间为9999999秒。

# File ext/pty/lib/expect.rb, line 32 def expect(pat,timeout=9999999) buf = '' case pat when String e_pat = Regexp.new(Regexp.quote(pat)) when Regexp e_pat = pat else raise TypeError, "unsupported pattern class: #{pat.class}" end @unusedBuf ||= '' while true if not @unusedBuf.empty? c = @unusedBuf.slice!(0).chr elsif !IO.select([self],nil,nil,timeout) or eof? then result = nil @unusedBuf = buf break else c = getc.chr end buf << c if $expect_verbose STDOUT.print c STDOUT.flush end if mat=e_pat.match(buf) then result = [buf,*mat.to_a[1..-1]] break end end if block_given? then yield result else return result end nil end

external_encoding → encoding

返回表示文件编码的Encoding对象。如果io是写入模式并且没有指定编码,则返回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) }

fcntl(integer_cmd, arg) → integer Show source

提供一种发布低级命令来控制或​​查询面向文件的I/O流的机制。参数和结果依赖于平台。如果arg是数字,则其值直接传递。如果它是一个字符串,则将其解释为二进制字节序列(Array#pack可能是构建此字符串的一种有用方法)。在Unix平台上,查看fcntl(2)详情。没有在所有平台上实施。

static VALUE rb_io_fcntl(int argc, VALUE *argv, VALUE io) { VALUE req, arg; rb_scan_args(argc, argv, "11", &req, &arg return rb_fcntl(io, req, arg }

fdatasync → 0 or nil

在立即写入所有缓冲数据的ios到磁盘。

如果底层操作系统不支持fdatasync(2)IO#fsync则会调用(可能会引发NotImplementedError)。

static VALUE rb_io_fdatasync(VALUE io) { rb_io_t *fptr; io = GetWriteIO(io GetOpenFile(io, fptr if (io_fflush(fptr) < 0) rb_sys_fail(0 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0) return INT2FIX(0 /* fall back */ return rb_io_fsync(io }

fileno → integer

to_i → integer

返回表示ios的数字文件描述符的整数。

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

static VALUE rb_io_fileno(VALUE io) { rb_io_t *fptr = RFILE(io)->fptr; int fd; rb_io_check_closed(fptr fd = fptr->fd; return INT2FIX(fd }

另外别名为:to_i

flush → ios

ios中的任何缓冲数据刷新到底层操作系统(请注意,这仅仅是Ruby内部缓冲;操作系统也可以缓冲数据)。

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

produces:

no newline

VALUE rb_io_flush(VALUE io) { return rb_io_flush_raw(io, 1 }

fsync → 0 or nil

在立即写入所有缓冲数据的ios到磁盘。请注意,fsync与使用不同IO#sync=。后者确保数据从Ruby的缓冲区刷新,但不保证底层操作系统实际将其写入磁盘。

NotImplementedError如果底层操作系统不支持fsync(2),则会引发此问题。

static VALUE rb_io_fsync(VALUE io) { rb_io_t *fptr; io = GetWriteIO(io GetOpenFile(io, fptr if (io_fflush(fptr) < 0) rb_sys_fail(0 if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0) rb_sys_fail_path(fptr->pathv return INT2FIX(0 }

getbyte → integer or nil

ios获取下一个8位字节(0..255)。nil如果在文件结尾处调用则返回。

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

VALUE rb_io_getbyte(VALUE io) { rb_io_t *fptr; int c; GetOpenFile(io, fptr rb_io_check_byte_readable(fptr READ_CHECK(fptr if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(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.ptr[fptr->rbuf.off-1]; return INT2FIX(c & 0xff }

getc → string or nil

ios读取一个字符的字符串。nil如果在文件结尾处调用则返回。

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

static VALUE rb_io_getc(VALUE io) { rb_io_t *fptr; rb_encoding *enc; GetOpenFile(io, fptr rb_io_check_char_readable(fptr enc = io_input_encoding(fptr READ_CHECK(fptr return io_getc(fptr, enc }

getch(min: nil, time: nil) → char

读取并返回原始模式下的字符。

您必须要求'io/console'才能使用此方法。

static VALUE console_getch(int argc, VALUE *argv, VALUE io) { rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts return ttymode(io, getc_call, set_rawmode, optp }

getpass(prompt=nil) → string

读取并返回没有回显的行。prompt除非是,否则打印nil

您必须要求'io/console'才能使用此方法。

static VALUE console_getpass(int argc, VALUE *argv, VALUE io) { VALUE str, wio; rb_check_arity(argc, 0, 1 wio = rb_io_get_write_io(io if (wio == io && io == rb_stdin) wio = rb_stderr; prompt(argc, argv, wio str = rb_ensure(getpass_call, io, puts_call, wio return str_chomp(str }

gets(sep=$/) → string or nil

gets(limit) → string or nil

gets(sep, limit) → string or nil

从I / O流中读取下一个“line”; 行由sep分隔。一个nil读取整个内容的分隔符,一个零长度分隔符一次读取一个段落的输入(输入单独段落中的两个连续换行符)。该流必须打开阅读或IOError将被提出。读入的行将被返回并分配给$_nil如果在文件结尾处调用则返回。如果第一个参数是一个整数,或者给出了可选的第二个参数,则返回的字符串不会超过以字节为单位的给定值。

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

如果IO包含多字节字符,则字节gets(1)将完全返回字符:

# Russian characters take 2 bytes File.write("testfile", "\u{442 435 441 442}") File.open("testfile") {|f|f.gets(1)} #=> "\u0442" File.open("testfile") {|f|f.gets(2)} #=> "\u0442" File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435" File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"

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

goto(p1, p2)

static VALUE console_goto(VALUE io, VALUE x, VALUE y) { rb_io_t *fptr; int fd; COORD pos; GetOpenFile(io, fptr fd = GetWriteFD(fptr pos.X = NUM2UINT(x pos.Y = NUM2UINT(y if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) { rb_syserr_fail(LAST_ERROR, 0 } return io; }

iflush

在内核中刷新输入缓冲区。

您必须要求'io/console'才能使用此方法。

static VALUE console_iflush(VALUE io) { rb_io_t *fptr; int fd; GetOpenFile(io, fptr fd = GetReadFD(fptr #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H if (tcflush(fd, TCIFLUSH)) rb_sys_fail(0 #endif (void)fd; return io; }

inspect → string

返回描述此IO对象的字符串。

static VALUE rb_io_inspect(VALUE obj) { rb_io_t *fptr; VALUE result; static const char closed[] = " (closed)"; fptr = RFILE(obj)->fptr; if (!fptr) return rb_any_to_s(obj result = rb_str_new_cstr("#<" rb_str_append(result, rb_class_name(CLASS_OF(obj)) rb_str_cat2(result, ":" if (NIL_P(fptr->pathv)) { if (fptr->fd < 0) { rb_str_cat(result, closed+1, strlen(closed)-1 } else { rb_str_catf(result, "fd %d", fptr->fd } } else { rb_str_append(result, fptr->pathv if (fptr->fd < 0) { rb_str_cat(result, closed, strlen(closed) } } return rb_str_cat2(result, ">" }

internal_encoding → encoding

如果指定了转换,则返回内部字符串的编码。否则返回零。

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

ioctl(integer_cmd, arg) → integer

提供一种发布低级命令来控制或​​查询I/O设备的机制。参数和结果依赖于平台。如果arg是数字,则其值直接传递。如果它是一个字符串,它将被解释为一个二进制字节序列。在Unix平台上,查看ioctl(2)详情。没有在所有平台上实施。

static VALUE rb_io_ioctl(int argc, VALUE *argv, VALUE io) { VALUE req, arg; rb_scan_args(argc, argv, "11", &req, &arg return rb_ioctl(io, req, arg }

ioflush

刷新内核中的输入和输出缓冲区。

您必须要求'io/console'才能使用此方法。

static VALUE console_ioflush(VALUE io) { rb_io_t *fptr; #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H int fd1, fd2; #endif GetOpenFile(io, fptr #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H fd1 = GetReadFD(fptr fd2 = GetWriteFD(fptr if (fd2 != -1 && fd1 != fd2) { if (tcflush(fd1, TCIFLUSH)) rb_sys_fail(0 if (tcflush(fd2, TCOFLUSH)) rb_sys_fail(0 } else { if (tcflush(fd1, TCIOFLUSH)) rb_sys_fail(0 } #endif return io; }

isatty → true or false

如果ios与终端设备(tty)关联则返回,false否则返回true

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

lineno → integer

返回ios中的当前行号。该流必须打开才能阅读。lineno统计被调用的次数,而不是所遇到的换行符的数量。如果使用换行符以外的分隔符调用get,则这两个值将有所不同。

像每个$/,行和readline一样使用的方法也会增加lineno

另请参阅$.变量。

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

static VALUE rb_io_lineno(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr rb_io_check_char_readable(fptr return INT2NUM(fptr->lineno }

lineno = integer → integer

手动将当前行号设置为给定值。$.仅在下次阅读时更新。

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

static VALUE rb_io_set_lineno(VALUE io, VALUE lineno) { rb_io_t *fptr; GetOpenFile(io, fptr rb_io_check_char_readable(fptr fptr->lineno = NUM2INT(lineno return lineno; }

lines(*args)

这是一个不推荐的别名each_line

static VALUE rb_io_lines(int argc, VALUE *argv, VALUE io) { rb_warn("IO#lines is deprecated; use #each_line instead" if (!rb_block_given_p()) return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv return rb_io_each_line(argc, argv, io }

noecho {|io| }

产量self与禁用回声返回。

STDIN.noecho(&:gets)

将读取并返回一个没有回显的行。

您必须要求'io/console'才能使用此方法。

static VALUE console_noecho(VALUE io) { return ttymode(io, rb_yield, set_noecho, NULL }

nonblock {|io| } → io

nonblock(boolean) {|io| } → io

self非阻塞模式产量。

false作为参数给出时,self在阻塞模式下产生。原始模式在块执行后恢复。

static VALUE rb_io_nonblock_block(int argc, VALUE *argv, VALUE io) { int nb = 1; rb_io_t *fptr; int f, restore[2]; GetOpenFile(io, fptr if (argc > 0) { VALUE v; rb_scan_args(argc, argv, "01", &v nb = RTEST(v } f = io_nonblock_mode(fptr->fd restore[0] = fptr->fd; restore[1] = f; if (!io_nonblock_set(fptr->fd, f, nb)) return rb_yield(io return rb_ensure(rb_yield, io, io_nonblock_restore, (VALUE)restore }

nonblock = boolean → boolean

当设定为在流启用非阻塞模式true,并且当设定为阻塞模式false

static VALUE rb_io_nonblock_set(VALUE io, VALUE nb) { rb_io_t *fptr; GetOpenFile(io, fptr if (RTEST(nb)) rb_io_set_nonblock(fptr else io_nonblock_set(fptr->fd, io_nonblock_mode(fptr->fd), RTEST(nb) return io; }

nonblock? → boolean

返回trueIO对象是否处于非阻塞模式。

static VALUE rb_io_nonblock_p(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr if (io_nonblock_mode(fptr->fd) & O_NONBLOCK) return Qtrue; return Qfalse; }

nread → int

返回可以不阻塞地读取的字节数。如果没有可用信息,则返回零。

static VALUE io_nread(VALUE io) { rb_io_t *fptr; int len; ioctl_arg n; GetOpenFile(io, fptr rb_io_check_readable(fptr len = rb_io_read_pending(fptr if (len > 0) return INT2FIX(len if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0 if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0 if (n > 0) return ioctl_arg2num(n return INT2FIX(0 }

oflush

在内核中刷新输出缓冲区。

您必须要求'io/console'才能使用此方法。

static VALUE console_oflush(VALUE io) { rb_io_t *fptr; int fd; GetOpenFile(io, fptr fd = GetWriteFD(fptr #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H if (tcflush(fd, TCOFLUSH)) rb_sys_fail(0 #endif (void)fd; return io; }

pathconf(p1)

使用fpathconf()返回路径名配置变量。

name应该是一个Etc始于其中的常量PC_

返回值是一个整数或零。零意味着无限期的限制。(fpathconf()返回-1,但未设置errno。)

require 'etc' IO.pipe {|r, w| p w.pathconf(Etc::PC_PIPE_BUF) #=> 4096 }

static VALUE io_pathconf(VALUE io, VALUE arg) { int name; long ret; rb_io_t *fptr; name = NUM2INT(arg GetOpenFile(io, fptr errno = 0; ret = fpathconf(fptr->fd, name if (ret == -1) { if (errno == 0) /* no limit */ return Qnil; rb_sys_fail("fpathconf" } return LONG2NUM(ret }

pid → integer

返回与ios关联的子进程的进程ID 。这将由设置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 }

pos → integer

返回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 pos -= fptr->rbuf.len; return OFFT2NUM(pos }

pos = integer → integer

ios中寻找给定的位置(以字节为单位)。当ios是textmode 时,不能保证找到正确的位置。

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

static VALUE rb_io_set_pos(VALUE io, VALUE offset) { rb_io_t *fptr; off_t pos; pos = NUM2OFFT(offset GetOpenFile(io, fptr pos = io_seek(fptr, pos, SEEK_SET if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv return OFFT2NUM(pos }

pressed?(p1)

static VALUE console_key_pressed_p(VALUE io, VALUE k) { int vk = -1; if (FIXNUM_P(k)) { vk = NUM2UINT(k } else { const struct vktable *t; const char *kn; if (SYMBOL_P(k)) { k = rb_sym2str(k kn = RSTRING_PTR(k } else { kn = StringValuePtr(k } t = console_win32_vk(kn, RSTRING_LEN(k) if (!t || (vk = (short)t->vk) == -1) { rb_raise(rb_eArgError, "unknown virtual key code: % "PRIsVALUE, k } } return GetKeyState(vk) & 0x80 ? Qtrue : Qfalse; }

print → nil

print(obj, ...) → nil

将给定的对象写入ios。返回nil

该流必须打开才能写入。每个给定的不是字符串的对象都将通过调用它的to_s方法进行转换。当没有参数被调用时,打印内容$_

如果输出字段分隔符($,)不是nil,则将其插入对象之间。如果输出记录separator($\)不是nil,则会将其附加到输出。

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

生产:

This is 100 percent.

VALUE rb_io_print(int argc, const VALUE *argv, VALUE out) { int i; VALUE line; /* if no argument given, print `$_' */ if (argc == 0) { argc = 1; line = rb_lastline_get( argv = &line; } for (i=0; i<argc; i++) { if (!NIL_P(rb_output_fs) && i>0) { rb_io_write(out, rb_output_fs } rb_io_write(out, argv[i] } if (argc > 0 && !NIL_P(rb_output_rs)) { rb_io_write(out, rb_output_rs } return Qnil; }

printf(format_string , obj, ...) → nil

格式化并写入ios,在格式字符串的控制下转换参数。详情请参阅Kernel#sprintf

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

putc(obj) → obj

如果OBJNumeric,写其代码是最不显著字节字符OBJ,否则写的字符串表示的第一个字节OBJIOS。注意:此方法不适用于多字节字符,因为它会截断它们。

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

生产:

AA

static VALUE rb_io_putc(VALUE io, VALUE ch) { VALUE str; if (RB_TYPE_P(ch, T_STRING)) { str = rb_str_substr(ch, 0, 1 } else { char c = NUM2CHR(ch str = rb_str_new(&c, 1 } rb_io_write(io, str return ch; }

puts(obj, ...) → nil

写入给定的对象(一个或多个),以IOSIO#print。在没有以换行符结束的任何之后写入换行符。

如果使用数组参数调用,则将每个元素写入新行。如果不带参数调用,则输出一个换行符。

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

produces:

this is a test

VALUE rb_io_puts(int argc, const 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 (RB_TYPE_P(argv[i], T_STRING)) { line = argv[i]; goto string; } if (rb_exec_recursive(io_puts_ary, argv[i], out)) { continue; } line = rb_obj_as_string(argv[i] string: rb_io_write(out, line if (RSTRING_LEN(line) == 0 || !str_end_with_asciichar(line, '\n')) { rb_io_write(out, rb_default_rs } } return Qnil; }

raw(min: nil, time: nil) {|io| }

self原始模式下的产量。

STDIN.raw(&:gets)

将读取并返回一个没有回显和行编辑的行。

您必须要求'io/console'才能使用此方法。

static VALUE console_raw(int argc, VALUE *argv, VALUE io) { rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts return ttymode(io, rb_yield, set_rawmode, optp }

raw!(min: nil, time: nil)

启用原始模式。

如果终端模式需要返回,请使用io.raw {...}。

您必须要求'io/console'才能使用此方法。

static VALUE console_set_raw(int argc, VALUE *argv, VALUE io) { conmode t; rb_io_t *fptr; int fd; rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts GetOpenFile(io, fptr fd = GetReadFD(fptr if (!getattr(fd, &t)) rb_sys_fail(0 set_rawmode(&t, optp if (!setattr(fd, &t)) rb_sys_fail(0 return io; }

read([length , outbuf]) → string, outbuf, or nil

从I/O流中读取长度字节。

长度必须是非负整数或nil

如果长度是一个正整数,它会尝试读取长度字节而不进行任何转换(二进制模式)。它返回nil或一个字符串,其长度为1至长度字节。nil意味着它在开始时遇到了EOF。1到长度为 -1字节的字符串表示在读取结果后它符合EOF。该长度的字节串意味着它不符合EOF。结果字符串始终是ASCII-8BIT编码。

如果长度被忽略或者是nil,它将读取直到EOF和编码转换被应用。即使在开始时遇到EOF,它也会返回一个字符串。

如果长度为零,则返回""

如果可选的outbuf参数存在,它必须引用一个String,它将接收数据。该outbuf中仅包含方法调用后接收到的数据,即使它不是在一开始是空的。

在文件结尾,它返回nil""取决于长度ios.read()和ios.read(nil)""并返回。ios.read(positive-integer)返回nil

f = File.new("testfile") f.read(16) #=> "This is line one" # reads whole file open("file") {|f| data = f.read # This returns a string even if the file is empty. ... } # iterate over fixed length records. open("fixed-record-file") {|f| while record = f.read(256) ... end } # iterate over variable length records. # record is prefixed by 32-bit length. open("variable-record-file") {|f| while len = f.read(4) len = len.unpack("N")[0] # 32-bit length record = f.read(len) # This returns a string even if len is 0. end }

请注意,此方法的行为与C中的fread()函数相同。这意味着它会重试以调用read(2)系统调用以读取具有指定长度(或直到EOF)的数据。即使ios是非阻塞模式,此行为也会被保留。(与其他方法一样,此方法对非阻塞标志不敏感)。如果您需要像read read(2)系统调用那样的行为,请考虑readpartial,#read_nonblock和sysread。

static VALUE io_read(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; long n, len; VALUE length, str; #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) int previous_mode; #endif rb_scan_args(argc, argv, "02", &length, &str if (NIL_P(length)) { GetOpenFile(io, fptr rb_io_check_char_readable(fptr return read_all(fptr, remain_size(fptr), str } len = NUM2LONG(length if (len < 0) { rb_raise(rb_eArgError, "negative length %ld given", len } io_setstrbuf(&str,len GetOpenFile(io, fptr rb_io_check_byte_readable(fptr if (len == 0) { io_set_read_length(str, 0 return str; } READ_CHECK(fptr #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) previous_mode = set_binary_mode_with_seek_cur(fptr #endif n = io_fread(str, 0, len, fptr io_set_read_length(str, n #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) if (previous_mode == O_TEXT) { setmode(fptr->fd, O_TEXT } #endif if (n == 0) return Qnil; OBJ_TAINT(str return str; }

read_nonblock(maxlen , options) → string

read_nonblock(maxlen, outbuf , options) → outbuf

在为基础文件描述符设置O_NONBLOCK后,使用read(2)系统调用从ios读取至多maxlen字节。

如果可选的outbuf参数存在,它必须引用一个String,它将接收数据。该outbuf中仅包含方法调用后接收到的数据,即使它不是在一开始是空的。

#read_nonblock只是调用read(2)系统调用。它会导致read(2)系统调用导致的所有错误:Errno::EWOULDBLOCK,Errno::EINTR等。调用者应该关心这样的错误。

如果该异常是Errno::EWOULDBLOCK或Errno::EAGAIN,则它由IO::WaitReadable扩展。所以IO::WaitReadable可以用来恢复重试read_nonblock的异常。

#read_nonblock在EOF上导致EOFError。

如果读取的字节缓冲区不是空的,#read_nonblock像readpartial那样从缓冲区读取数据。在这种情况下,不会调用read(2)系统调用。

当#read_nonblock引发一个IO::WaitReadable类型的异常时,在读取io以避免繁忙循环之前,不应调用#read_nonblock。这可以如下完成。

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

尽管#read_nonblock不会引发IO::WaitWritable。OpenSSL::Buffering#read_nonblock可以引发IO::WaitWritable。如果IO和SSL应该多态使用,IO::WaitWritable也应该被救出。查看示例代码的OpenSSL::Buffering#read_nonblock文档。

请注意,除非设置了非阻塞标志,否则此方法与readpartial相同。

通过指定关键字参数异常false,你可以指出#read_nonblock应该不会引发IO :: WaitReadable异常,但返回的符号:wait_readable来代替。在EOF中,它将返回nil而不是引发EOFError。

# File prelude.rb, line 75 def read_nonblock(len, buf = nil, exception: true) __read_nonblock(len, buf, exception) end

readbyte → integer

像读取一个字节一样IO#getbyte,但会引起EOFError文件结束。

static VALUE rb_io_readbyte(VALUE io) { VALUE c = rb_io_getbyte(io if (NIL_P(c)) { rb_eof_error( } return c; }

readchar → string

ios读取一个字符的字符串。引发EOFError文件结尾。

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

readline(sep=$/) → string

readline(limit) → string

readline(sep, limit) → string

读取一行IO#gets,但引发EOFError文件结束。

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

readlines(sep=$/) → array

readlines(limit) → array

readlines(sep, limit) → array

读取ios中的所有行,并将它们返回到数组中。行由可选的sep分隔。如果九月nil,流的其余部分被返回为单个记录。如果第一个参数是一个整数,或者给出了可选的第二个参数,则返回的字符串不会超过以字节为单位的给定值。该流必须打开阅读或IOError将被提出。

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

static VALUE rb_io_readlines(int argc, VALUE *argv, VALUE io) { struct getline_arg args; prepare_getline_args(argc, argv, &args, io return io_readlines(&args, io }

readpartial(maxlen) → string

readpartial(maxlen, outbuf) → outbuf

从I / O流中最多读取maxlen字节。它仅在ios没有立即可用数据时阻塞。如果有一些数据可用,它不会阻止。如果可选的outbuf参数存在,它必须引用一个String,它将接收数据。该outbuf中仅包含方法调用后接收到的数据,即使它不是在一开始是空的。它EOFError在文件结尾处引发。

readpartial是为诸如管道,套接字,tty等流设计的,只有当没有数据立即可用时才会阻塞。这意味着它只有在遵循所有条件时才会阻止。

  • IO对象中的字节缓冲区为空。

  • 流的内容是空的。

  • 流未达到EOF。当读取部分块时,它等待流上的数据或EOF。如果达到某些数据,readpartial将返回数据。如果达到EOF,则readpartial引发EOFError。当readpartial不阻塞时,它立即返回或提升。如果字节缓冲区不是空的,它将返回缓冲区中的数据。否则,如果流有一些内容,它将返回流中的数据。否则,如果数据流达到EOF,则会引发EOFError.r,w = IO.pipe#buffer pipe content w <<“abc”#“”“abc”。r.readpartial(4096)#=>“abc”“”“”r.readpartial(4096)#blocks因为缓冲区和管道是空的。r,w = 10。readpartial(4096)#=>“ghi \ n”“”“”请注意,readpartial的行为类似于sysread。差异是:

  • 如果字节缓冲区不为空,则从字节缓冲区读取而不是“缓冲IO(IOError)的系统读取”。

  • 它不会导致Errno::EWOULDBLOCK和Errno::EINTR。当readpartial通过读系统调用遇到EWOULDBLOCK和EINTR时,readpartial重试系统调用。

后者意味着readpartial是非阻塞标志不敏感的。它阻止#sysread导致Errno::EWOULDBLOCK的情况,就好像fd是阻塞模式一样。

static VALUE io_readpartial(int argc, VALUE *argv, VALUE io) { VALUE ret; ret = io_getpartial(argc, argv, io, Qnil, 0 if (NIL_P(ret)) rb_eof_error( return ret; }

ready? → true, false or nil

如果输入可用而不阻塞,则返回true;否则返回false。如果没有可用信息,则返回nil。

static VALUE io_ready_p(VALUE io) { rb_io_t *fptr; struct timeval tv = {0, 0}; GetOpenFile(io, fptr rb_io_check_readable(fptr if (rb_io_read_pending(fptr)) return Qtrue; if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv)) return Qtrue; return Qfalse; }

reopen(other_IO) → ios

reopen(path, mode_str) → ios

iosother_IO中给出的I/O流重新关联,或重新关联路径上打开的新流。这可能动态地改变这个流的实际类别。

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, opt; int oflags; rb_io_t *fptr; if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 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 = ZALLOC(rb_io_t } if (!NIL_P(nmode) || !NIL_P(opt)) { int fmode; convconfig_t convconfig; rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig 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; fptr->encs = convconfig; } else { oflags = rb_io_fmode_oflags(fptr->mode } fptr->pathv = fname; if (fptr->fd < 0) { fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666 fptr->stdio_file = 0; return file; } if (fptr->mode & FMODE_WRITABLE) { if (io_fflush(fptr) < 0) rb_sys_fail(0 } fptr->rbuf.off = fptr->rbuf.len = 0; if (fptr->stdio_file) { int e = rb_freopen(rb_str_encode_ospath(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file if (e) rb_syserr_fail_path(e, fptr->pathv fptr->fd = fileno(fptr->stdio_file rb_fd_fix_cloexec(fptr->fd #ifdef USE_SETVBUF if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0) rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv #endif if (fptr->stdio_file == stderr) { if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0) rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv } else if (fptr->stdio_file == stdout && isatty(fptr->fd)) { if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0) rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv } } else { int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666 int err = 0; if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0) err = errno; (void)close(tmpfd if (err) { rb_syserr_fail_path(err, fptr->pathv } } return file; }

rewind → 0

ios置于输入的开头,重置lineno为零。

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

请注意,它不能用于诸如管道,ttys和套接字之类的流。

static VALUE rb_io_rewind(VALUE io) { rb_io_t *fptr; GetOpenFile(io, fptr if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv if (io == ARGF.current_file) { ARGF.lineno -= fptr->lineno; } fptr->lineno = 0; if (fptr->readconv) { clear_readconv(fptr } return INT2FIX(0 }

scanf(str) { |current_match| ... }

扫描当前字符串,直到匹配耗尽,在字符串中遇到每个匹配时产生每个匹配。一个块不是必需的,因为结果将被简单地聚合到最终的数组中。

"123 456".block_scanf("%d") # => [123, 456]

如果给出了块,则从yield返回的值将被添加到输出数组中。

"123 456".block_scanf("%d") do |digit,| # the ',' unpacks the Array digit + 100 end # => [223, 556]

有关创建格式字符串的详细信息,请参阅Scanf。

你将需要'scanf'来使用#scanf。

# File lib/scanf.rb, line 613 def scanf(str,&b) #:yield: current_match return block_scanf(str,&b) if b return [] unless str.size > 0 start_position = pos rescue 0 matched_so_far = 0 source_buffer = "" result_buffer = [] final_result = [] fstr = Scanf::FormatString.new(str) loop do if eof || (tty? &&! fstr.match(source_buffer)) final_result.concat(result_buffer) break end source_buffer << gets current_match = fstr.match(source_buffer) spec = fstr.last_spec_tried if spec.matched if spec.mid_match? result_buffer.replace(current_match) next end elsif (fstr.matched_count == fstr.spec_count - 1) if /\A\s*\z/.match(fstr.string_left) break if spec.count_space? result_buffer.replace(current_match) next end end final_result.concat(current_match) matched_so_far += source_buffer.size source_buffer.replace(fstr.string_left) matched_so_far -= source_buffer.size break if fstr.last_spec fstr.prune end begin seek(start_position + matched_so_far, IO::SEEK_SET) rescue Errno::ESPIPE end soak_up_spaces if fstr.last_spec && fstr.space return final_result end

seek(amount, whence=IO::SEEK_SET) → 0 Show source

根据whence的值寻找流中给定的偏移anInteger

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

例:

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 = interpret_seek_whence(ptrname } return rb_io_seek(io, offset, whence }

set_encoding(ext_enc) → io

set_encoding("ext_enc:int_enc") → io

set_encoding(ext_enc, int_enc) → io

set_encoding("ext_enc:int_enc", opt) → io

set_encoding(ext_enc, int_enc, opt) → io

如果指定单参数,则从io读取的字符串将使用指定的编码进行标记。如果编码是以冒号分隔的两个编码名称“A:B”,则读取的字符串从编码A(外部编码)转换为编码B(内部编码),然后用B标记。如果指定了两个参数,则这些参数必须是编码对象或编码名称,第一个是外部编码,第二个是内部编码。如果指定了外部编码和内部编码,则可选散列参数指定转换选项。

static VALUE rb_io_set_encoding(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; VALUE v1, v2, opt; if (!RB_TYPE_P(io, T_FILE)) { return rb_funcallv(io, id_set_encoding, argc, argv } argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt GetOpenFile(io, fptr io_encoding_set(fptr, v1, v2, opt return io; }

stat → stat

ios的状态信息作为类型的对象返回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; GetOpenFile(obj, fptr if (fstat(fptr->fd, &st) == -1) { rb_sys_fail_path(fptr->pathv } return rb_stat_new(&st }

sync → true or false

返回ios的当前“同步模式” 。当同步模式为true时,所有输出将立即刷新到底层操作系统,而不会由Ruby在内部进行缓冲。另见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; }

sync = boolean → boolean

将“同步模式”设置为truefalse。当同步模式为真时,所有输出立即刷新到底层操作系统,而不会在内部进行缓冲。返回新的状态。另见IO#fsync

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

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

sysread(maxlen, outbuf) → string

使用低级读取从ios读取maxlen字节并将其作为字符串返回。不要与从ios读取的其他方法混用,否则可能会得到不可预知的结果。如果可选的outbuf参数存在,它必须引用一个String,它将接收数据。该outbuf中仅包含方法调用后接收到的数据,即使它不是在一开始是空的。在错误和文件结尾处引发。SystemCallErrorEOFError

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; struct read_internal_arg arg; rb_scan_args(argc, argv, "11", &len, &str ilen = NUM2LONG(len io_setstrbuf(&str,ilen if (ilen == 0) return str; GetOpenFile(io, fptr rb_io_check_byte_readable(fptr if (READ_DATA_BUFFERED(fptr)) { rb_raise(rb_eIOError, "sysread for buffered IO" } /* * FIXME: removing rb_thread_wait_fd() here changes sysread semantics * on non-blocking IOs. However, it's still currently possible * for sysread to raise Errno::EAGAIN if another thread read()s * the IO after we return from rb_thread_wait_fd() but before * we call read() */ rb_thread_wait_fd(fptr->fd rb_io_check_closed(fptr io_setstrbuf(&str, ilen rb_str_locktmp(str arg.fd = fptr->fd; arg.str_ptr = RSTRING_PTR(str arg.len = ilen; rb_ensure(read_internal_call, (VALUE)&arg, rb_str_unlocktmp, str n = arg.len; if (n == -1) { rb_sys_fail_path(fptr->pathv } io_set_read_length(str, n if (n == 0 && ilen > 0) { rb_eof_error( } OBJ_TAINT(str return str; }

sysseek(offset, whence=IO::SEEK_SET) → integer

旨在给定偏移量根据所述值的流中的何处(参看IO#seek为值何处)。返回文件中的新偏移量

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 = interpret_seek_whence(ptrname } pos = NUM2OFFT(offset GetOpenFile(io, fptr if ((fptr->mode & FMODE_READABLE) && (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) { rb_raise(rb_eIOError, "sysseek for buffered IO" } if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) { rb_warn("sysseek for buffered IO" } errno = 0; pos = lseek(fptr->fd, pos, whence if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv return OFFT2NUM(pos }

syswrite(string) → integer

使用低级写入将给定的字符串写入ios。返回写入的字节数。不要与写入ios的其他方法混用,否则可能会得到不可预知的结果。SystemCallError错误引发。

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

static VALUE rb_io_syswrite(VALUE io, VALUE str) { VALUE tmp; rb_io_t *fptr; long n, len; const char *ptr; if (!RB_TYPE_P(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" } tmp = rb_str_tmp_frozen_acquire(str RSTRING_GETMEM(tmp, ptr, len n = rb_write_internal(fptr->fd, ptr, len if (n == -1) rb_sys_fail_path(fptr->pathv rb_str_tmp_frozen_release(str, tmp return LONG2FIX(n }

tell → integer

返回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 pos -= fptr->rbuf.len; return OFFT2NUM(pos }

to_i()

别名为:fileno

to_io → ios

返回ios

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

tty?→true或false显示来源

如果ios与终端设备(tty)关联则返回true,否则返回false

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

ungetbyte(string) → nil

ungetbyte(integer) → nil

将字节(作为参数传递)推回到ios上,以便随后的缓冲读取将返回它。在后续的读取操作之前,只有一个字节可能被推回(也就是说,您将只能读取已被推回的几个字节中的最后一个字节)。对未缓冲的读取(例如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_byte_readable(fptr if (NIL_P(b)) return Qnil; if (FIXNUM_P(b)) { char cc = FIX2INT(b b = rb_str_new(&cc, 1 } else { SafeStringValue(b } io_ungetbyte(b, fptr return Qnil; }

ungetc(string) → nil

将一个字符(作为参数传递)推回到ios上,以便后续的缓存字符读取将返回它。在后续的读取操作之前,只有一个字符可能会被推回(也就是说,您将只能读取已被推回的几个字符中的最后一个字符)。对未缓冲的读取(例如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_char_readable(fptr if (NIL_P(c)) return Qnil; if (FIXNUM_P(c)) { c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr) } else if (RB_TYPE_P(c, T_BIGNUM)) { c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr) } else { SafeStringValue(c } if (NEED_READCONV(fptr)) { SET_BINARY_MODE(fptr len = RSTRING_LEN(c #if SIZEOF_LONG > SIZEOF_INT if (len > INT_MAX) rb_raise(rb_eIOError, "ungetc failed" #endif make_readconv(fptr, (int)len if (fptr->cbuf.capa - fptr->cbuf.len < len) rb_raise(rb_eIOError, "ungetc failed" if (fptr->cbuf.off < len) { MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len, fptr->cbuf.ptr+fptr->cbuf.off, char, fptr->cbuf.len fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len; } fptr->cbuf.off -= (int)len; fptr->cbuf.len += (int)len; MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len } else { NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr io_ungetbyte(c, fptr } return Qnil; }

wait(timeout = nil, mode = :read) → IO, true or nil

一直等到IO可读或可写,而不会阻塞并返回self,或者nil超时。true缓冲数据可用时立即返回。可选参数mode是一个:read:write:read_write

static VALUE io_wait_readwrite(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; struct timeval timerec; struct timeval *tv = NULL; int event = 0; int i; GetOpenFile(io, fptr for (i = 0; i < argc; ++i) { if (SYMBOL_P(argv[i])) { event |= wait_mode_sym(argv[i] } else { *(tv = &timerec) = rb_time_interval(argv[i] } } /* rb_time_interval() and might_mode() might convert the argument */ rb_io_check_closed(fptr if (!event) event = RB_WAITFD_IN; if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr)) return Qtrue; if (wait_for_single_fd(fptr, event, tv)) return io; return Qnil; }

wait_readable → IO, true or nil

wait_readable(timeout) → IO, true or nil

等到IO可读而没有阻塞并返回self,或者nil超时。缓冲数据可用时立即返回true

static VALUE io_wait_readable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; struct timeval timerec; struct timeval *tv; GetOpenFile(io, fptr rb_io_check_readable(fptr tv = get_timeout(argc, argv, &timerec if (rb_io_read_pending(fptr)) return Qtrue; if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) { return io; } return Qnil; }

wait_writable → IO

wait_writable(timeout) → IO or nil

等到IO可写且没有阻塞并返回selfnil超时。

static VALUE io_wait_writable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; struct timeval timerec; struct timeval *tv; GetOpenFile(io, fptr rb_io_check_writable(fptr tv = get_timeout(argc, argv, &timerec if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) { return io; } return Qnil; }

winsize → rows, columns()

返回控制台大小。

您必须要求'io/console'才能使用此方法。

static VALUE console_winsize(VALUE io) { rb_io_t *fptr; int fd; rb_console_size_t ws; GetOpenFile(io, fptr fd = GetWriteFD(fptr if (!getwinsize(fd, &ws)) rb_sys_fail(0 return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)) }

winsize = rows, columns()

尝试设置控制台大小。效果取决于平台和运行环境。

您必须要求'io/console'才能使用此方法。

static VALUE console_set_winsize(VALUE io, VALUE size) { rb_io_t *fptr; rb_console_size_t ws; #if defined _WIN32 HANDLE wh; int newrow, newcol; #endif VALUE row, col, xpixel, ypixel; const VALUE *sz; int fd; long sizelen; GetOpenFile(io, fptr size = rb_Array(size if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) { rb_raise(rb_eArgError, "wrong number of arguments (given %ld, expected 2 or 4)", sizelen } sz = RARRAY_CONST_PTR(size row = sz[0], col = sz[1], xpixel = ypixel = Qnil; if (sizelen == 4) xpixel = sz[2], ypixel = sz[3]; fd = GetWriteFD(fptr #if defined TIOCSWINSZ ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0; #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row SET(col SET(xpixel SET(ypixel #undef SET if (!setwinsize(fd, &ws)) rb_sys_fail(0 #elif defined _WIN32 wh = (HANDLE)rb_w32_get_osfhandle(fd #define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row SET(col #undef SET if (!NIL_P(xpixel)) (void)NUM2UINT(xpixel if (!NIL_P(ypixel)) (void)NUM2UINT(ypixel if (!GetConsoleScreenBufferInfo(wh, &ws)) { rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo" } if ((ws.dwSize.X < newcol && (ws.dwSize.X = newcol, 1)) || (ws.dwSize.Y < newrow && (ws.dwSize.Y = newrow, 1))) { if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) { rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo" } } ws.srWindow.Left = 0; ws.srWindow.Top = 0; ws.srWindow.Right = newcol; ws.srWindow.Bottom = newrow; if (!SetConsoleWindowInfo(wh, FALSE, &ws.srWindow)) { rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo" } #endif return io; }

write(string) → integer

将给定的字符串写入ios。该流必须打开才能写入。如果参数不是字符串,它将被转换为使用的字符串to_s。返回写入的字节数。

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 }

write_nonblock(string) → integer

write_nonblock(string , options) → integer

在为基础文件描述符设置O_NONBLOCK后,使用write(2)系统调用将给定的字符串写入ios

它返回写入的字节数。

#write_nonblock只是调用write(2)系统调用。它会导致write(2)系统调用导致的所有错误:Errno::EWOULDBLOCK,Errno::EINTR等。结果也可能小于string.length(部分写入)。调用者应该关心这样的错误和部分写入。

如果该异常是Errno :: EWOULDBLOCK或Errno :: EAGAIN,则它由IO :: WaitWritable扩展。所以IO :: WaitWritable可以用来恢复重试write_nonblock的异常。

# Creates a pipe. r, w = IO.pipe # write_nonblock writes only 65536 bytes and return 65536. # (The pipe size is 65536 bytes on this environment.) s = "a" * 100000 p w.write_nonblock(s) #=> 65536 # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN). p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN)

如果写入缓冲区不是空的,它首先被刷新。

当#write_nonblock引发异常类型的IO::WaitWritable时,不应调用#write_nonblock,直到io可写,以避免繁忙循环。这可以如下完成。

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

请注意,这并不保证写入字符串中的所有数据。写入的长度将作为结果报告,并且应在稍后检查。

在某些平台(如Windows)上,根据IO对象的种类不支持#write_nonblock。在这种情况下,#write_nonblock引发Errno::EBADF

通过指定关键字参数异常false,你可以指出#write_nonblock应该不会引发IO :: WaitWritable异常,但返回的符号:wait_writable来代替。

# File prelude.rb, line 133 def write_nonblock(buf, exception: true) __write_nonblock(buf, exception) end

私有实例方法

block_scanf(str) { |current| ... }

# File lib/scanf.rb, line 681 def block_scanf(str) final = [] # Sub-ideal, since another FS gets created in scanf. # But used here to determine the number of specifiers. fstr = Scanf::FormatString.new(str) last_spec = fstr.last_spec begin current = scanf(str) break if current.empty? final.push(yield(current)) end until eof || fstr.last_spec_tried == last_spec return final end

soak_up_spaces()

# File lib/scanf.rb, line 672 def soak_up_spaces c = getc ungetc(c) if c until eof ||! c || /\S/.match(c.chr) c = getc end ungetc(c) if (c && /\S/.match(c.chr)) end