Spec-Zone.ru › Ruby 2.4

класс IO

Родитель:
Объект
Включенные модули:
File::Constants, Enumerable

Библиотека expect добавляет метод экземпляра IO expect, который выполняет действия, аналогичные расширению expect в tcl.

Для использования этого метода необходимо загрузить expect:

require 'expect'

Подробности использования см. в expect.

Класс IO является основой для всех операций ввода-вывода в Ruby. Поток ввода-вывода может быть дуплексным (то есть двунаправленным) и поэтому может использовать более одного потока операционной системы.

Многие примеры в этом разделе используют класс File, единственный стандартный подкласс класса IO. Эти два класса тесно связаны. Как и класс File, библиотека Socket наследуется от IO (например, TCPSocket или UDPSocket).

Метод Kernel#open может создавать объект IO (или File) для следующих типов аргументов:

  • Простая строка представляет имя файла, подходящее для операционной системы.

  • Строка, начинающаяся с "|" , указывает на дочерний процесс. Остальная часть строки после "|" выполняется как процесс с соответствующими каналами ввода/вывода, подключенными к нему.

  • Строка, равная "|-" , создаст другой экземпляр Ruby как дочерний процесс.

Объект IO может быть открыт с различными режимами файла (только чтение, только запись) и кодировками для правильного преобразования. Смотрите ::new для этих опций. Для получения подробностей различных форматов команд, описанных выше, см. Kernel#open.

::popen, библиотека Open3 или Process#spawn также могут использоваться для связи с дочерними процессами через IO.

Ruby будет преобразовывать имена путей между различными соглашениями операционных систем, если это возможно. Например, в системе Windows имя файла "/gumby/ruby/test.rb" будет открыто как "\gumby\ruby\test.rb". При указании имени файла в стиле Windows в строке Ruby помните, что нужно экранировать обратные косые черты:

"C:\\gumby\\ruby\\test.rb"

В наших примерах здесь будут использоваться косые черты в стиле Unix; File::ALT_SEPARATOR можно использовать для получения символа разделителя, специфичного для платформы.

Глобальная константа ARGF (также доступная как $<) предоставляет поток типа IO, который позволяет получить доступ ко всем файлам, упомянутым в командной строке (или STDIN, если файлы не указаны). ARGF#path и его псевдоним ARGF#filename предназначены для доступа к имени файла, который в данный момент читается.

io/console

Расширение io/console предоставляет методы для взаимодействия с консолью. К консоли можно получить доступ из ::console или стандартных объектов ввода/вывода/ошибок IO.

Загрузка io/console добавляет следующие методы:

  • ::console

  • #raw

  • #raw!

  • #cooked

  • #cooked!

  • #getch

  • #echo=

  • #echo?

  • #noecho

  • #winsize

  • #winsize=

  • #iflush

  • #ioflush

  • #oflush

Пример:

require 'io/console'
rows, columns = $stdout.winsize
puts "Your screen is #{columns} wide and #{rows} tall"

Константы

EWOULDBLOCKWaitReadable

EAGAINWaitReadable

EWOULDBLOCKWaitWritable

EAGAINWaitWritable

SEEK_CUR

Установить позицию ввода-вывода с текущей позиции

SEEK_DATA

Установить позицию ввода-вывода в следующую позицию, содержащую данные

SEEK_END

Установить позицию ввода-вывода с конца

SEEK_HOLE

Установить позицию ввода-вывода в следующую дыру

SEEK_SET

Установить позицию ввода-вывода с начала

Методы публичного класса

binread(name, [length [, offset]] ) → string Показать исходный код
static VALUE
rb_io_s_binread(int argc, VALUE *argv, VALUE io)
{
    VALUE offset;
    struct foreach_arg arg;
    enum {
        fmode = FMODE_READABLE|FMODE_BINMODE,
        oflags = O_RDONLY
#ifdef O_BINARY
                |O_BINARY
#endif
    };
    convconfig_t convconfig = {NULL, NULL, 0, Qnil};

    rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
    FilePathValue(argv[0]);
    convconfig.enc = rb_ascii8bit_encoding();
    arg.io = rb_io_open_generic(argv[0], oflags, fmode, &convconfig, 0);
    if (NIL_P(arg.io)) return Qnil;
    arg.argv = argv+1;
    arg.argc = (argc > 1) ? 1 : 0;
    if (!NIL_P(offset)) {
        struct seek_arg sarg;
        int state = 0;
        sarg.io = arg.io;
        sarg.offset = offset;
        sarg.mode = SEEK_SET;
        rb_protect(seek_before_access, (VALUE)&sarg, &state);
        if (state) {
            rb_io_close(arg.io);
            rb_jump_tag(state);
        }
    }
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}

Открывает файл, по желанию переходит к заданному смещению, затем возвращает length байтов (по умолчанию — остаток файла). binread гарантирует закрытие файла перед возвратом. Режим открытия будет «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 "
binwrite(name, string, [offset] ) → integer Показать исходный код
binwrite(name, string, [offset], open_args ) → integer
static VALUE
rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
{
    return io_s_write(argc, argv, 1);
}

То же, что и IO.write, но открывает файл в двоичном режиме с кодировкой ASCII-8BIT («wb:ASCII-8BIT»).

console → #<File:/dev/tty> Показать исходный код
console(sym, *args)
static VALUE
console_dev(int argc, VALUE *argv, VALUE klass)
{
    VALUE con = 0;
    rb_io_t *fptr;
    VALUE sym = 0;

    rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS);
    if (argc) {
        Check_Type(sym = argv[0], T_SYMBOL);
    }
    if (klass == rb_cIO) klass = rb_cFile;
    if (rb_const_defined(klass, id_console)) {
        con = rb_const_get(klass, id_console);
        if (!RB_TYPE_P(con, T_FILE) ||
            (!(fptr = RFILE(con)->fptr) || GetReadFD(fptr) == -1)) {
            rb_const_remove(klass, id_console);
            con = 0;
        }
    }
    if (sym) {
        if (sym == ID2SYM(id_close) && argc == 1) {
            if (con) {
                rb_io_close(con);
                rb_const_remove(klass, id_console);
                con = 0;
            }
            return Qnil;
        }
    }
    if (!con) {
        VALUE args[2];
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
# define CONSOLE_DEVICE "/dev/tty"
#elif defined _WIN32
# define CONSOLE_DEVICE "con$"
# define CONSOLE_DEVICE_FOR_READING "conin$"
# define CONSOLE_DEVICE_FOR_WRITING "conout$"
#endif
#ifndef CONSOLE_DEVICE_FOR_READING
# define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
#endif
#ifdef CONSOLE_DEVICE_FOR_WRITING
        VALUE out;
        rb_io_t *ofptr;
#endif
        int fd;

#ifdef CONSOLE_DEVICE_FOR_WRITING
        fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0);
        if (fd < 0) return Qnil;
        rb_update_max_fd(fd);
        args[1] = INT2FIX(O_WRONLY);
        args[0] = INT2NUM(fd);
        out = rb_class_new_instance(2, args, klass);
#endif
        fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_READING, O_RDWR, 0);
        if (fd < 0) {
#ifdef CONSOLE_DEVICE_FOR_WRITING
            rb_io_close(out);
#endif
            return Qnil;
        }
        rb_update_max_fd(fd);
        args[1] = INT2FIX(O_RDWR);
        args[0] = INT2NUM(fd);
        con = rb_class_new_instance(2, args, klass);
        GetOpenFile(con, fptr);
        fptr->pathv = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
#ifdef CONSOLE_DEVICE_FOR_WRITING
        GetOpenFile(out, ofptr);
        ofptr->pathv = fptr->pathv;
        fptr->tied_io_for_writing = out;
        ofptr->mode |= FMODE_SYNC;
#endif
        fptr->mode |= FMODE_SYNC;
        rb_const_set(klass, id_console, con);
    }
    if (sym) {
        return rb_f_send(argc, argv, con);
    }
    return con;
}

Возвращает экземпляр File, открытый в консоли.

Если sym задан, он будет отправлен в открытую консоль с args и результат будет возвращён вместо самой консольной IO.

Для использования этого метода необходимо подключить 'io/console'.

copy_stream(src, dst) Показать исходный код
copy_stream(src, dst, copy_length)
copy_stream(src, dst, copy_length, src_offset)
static VALUE
rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
{
    VALUE src, dst, length, src_offset;
    struct copy_stream_struct st;

    MEMZERO(&st, struct copy_stream_struct, 1);

    rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);

    st.src = src;
    st.dst = dst;

    if (NIL_P(length))
        st.copy_length = (off_t)-1;
    else
        st.copy_length = NUM2OFFT(length);

    if (NIL_P(src_offset))
        st.src_offset = (off_t)-1;
    else
        st.src_offset = NUM2OFFT(src_offset);

    rb_fd_init(&st.fds);
    rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);

    return OFFT2NUM(st.total);
}

::copy_stream копирует src в dst. src и dst могут быть именем файла или IO.

Этот метод возвращает количество скопированных байтов.

Если необязательные аргументы не заданы, начальная позиция копирования — начало файла или текущее смещение в IO. Конечная позиция копирования — конец файла.

Если задан copy_length, то скопировано не более copy_length байтов.

Если задан src_offset, он указывает начальную позицию копирования.

При заданном src_offset и src в качестве IO, ::copy_stream не перемещает текущее смещение файла.

for_fd(fd, mode [, opt]) → io Показать исходный код
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;
}

Синоним для IO.new.

foreach(name, sep=$/ [, open_args]) {|line| block } → nil Показать исходный код
foreach(name, limit [, open_args]) {|line| block } → nil
foreach(name, sep, limit [, open_args]) {|line| block } → nil
foreach(...) → an_enumerator
static VALUE
rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
{
    VALUE opt;
    int orig_argc = argc;
    struct foreach_arg arg;
    struct getline_arg garg;

    argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
    RETURN_ENUMERATOR(self, orig_argc, argv);
    extract_getline_args(argc-1, argv+1, &garg);
    open_key_args(argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    extract_getline_opts(opt, &garg);
    check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
    return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
}

Выполняет блок для каждой строки в указанном I/O порте, где строки разделены sep.

Если блок не задан, возвращается перечислитель.

IO.foreach("testfile") {|x| print "GOT ", x }

результат:

GOT This is line one
GOT This is line two
GOT This is line three
GOT And so on...

Если последний аргумент — хэш, это ключевые аргументы для открытия. Подробнее см. IO.read.

new(fd [, mode] [, opt]) → io Показать исходный код
static VALUE
rb_io_initialize(int argc, VALUE *argv, VALUE io)
{
    VALUE fnum, vmode;
    rb_io_t *fp;
    int fd, fmode, oflags = O_RDONLY;
    convconfig_t convconfig;
    VALUE opt;
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    int ofmode;
#else
    struct stat st;
#endif


    argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
    rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);

    fd = NUM2INT(fnum);
    if (rb_reserved_fd_p(fd)) {
        rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
    }
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    oflags = fcntl(fd, F_GETFL);
    if (oflags == -1) rb_sys_fail(0);
#else
    if (fstat(fd, &st) == -1) rb_sys_fail(0);
#endif
    rb_update_max_fd(fd);
#if defined(HAVE_FCNTL) && defined(F_GETFL)
    ofmode = rb_io_oflags_fmode(oflags);
    if (NIL_P(vmode)) {
        fmode = ofmode;
    }
    else if ((~ofmode & fmode) & FMODE_READWRITE) {
        VALUE error = INT2FIX(EINVAL);
        rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
    }
#endif
    if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
        fmode |= FMODE_PREP;
    }
    MakeOpenFile(io, fp);
    fp->fd = fd;
    fp->mode = fmode;
    fp->encs = convconfig;
    clear_codeconv(fp);
    io_check_tty(fp);
    if (fileno(stdin) == fd)
        fp->stdio_file = stdin;
    else if (fileno(stdout) == fd)
        fp->stdio_file = stdout;
    else if (fileno(stderr) == fd)
        fp->stdio_file = stderr;

    if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
    return io;
}

Возвращает новый объект IO (поток) для заданного целочисленного дескриптора файла fd и mode строки. opt можно использовать для указания частей mode более читаемым образом. См. также ::sysopen и ::for_fd.

::new вызывается различными методами открытия File и IO, такими как ::open, Kernel#open и File.open.

Режим открытия

Когда mode — целое число, оно должно быть комбинацией режимов, определённых в File::Constants (File::RDONLY, +File::WRONLY | File::CREAT+). См. страницу руководства open(2) для получения дополнительной информации.

Когда mode — строка, она должна иметь один из следующих форматов:

fmode
fmode ":" ext_enc
fmode ":" ext_enc ":" int_enc
fmode ":" "BOM|UTF-*"

fmode — строка режима открытия IO, ext_enc — внешняя кодировка для IO, а int_enc — внутренняя кодировка.

Режим открытия IO

Ruby допускает следующие режимы открытия:

"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, each write call appends data at end of file.
     Creates a new file for writing if file does not exist.

"a+" Read-write, each write call appends data at end of file.
     Creates a new file for reading and writing if file does
     not exist.

Следующие режимы должны использоваться отдельно и вместе с одним или несколькими режимами, указанными выше.

"b"  Binary file mode
     Suppresses EOL <-> CRLF conversion on Windows. And
     sets external encoding to ASCII-8BIT unless explicitly
     specified.

"t"  Text file mode

Если режим открытия исходного IO — только чтение, его нельзя изменить на запись. Аналогично, режим открытия нельзя изменить с записи на чтение.

При попытке такого изменения ошибка возникает в разных местах в зависимости от платформы.

IO Кодировка

Если ext_enc указан, при чтении строки будут помечены кодировкой, а при записи строки будут преобразованы в указанную кодировку.

Если ext_enc и int_enc указаны, строки чтения будут преобразованы из ext_enc в int_enc при вводе, а строки записи — из int_enc в ext_enc при выводе. См. Кодировка для получения дополнительных сведений о преобразовании кодировок при вводе и выводе.

Если используются «BOM|UTF-8», «BOM|UTF-16LE» или «BOM|UTF16-BE», Ruby проверяет наличие BOM Unicode в входном документе, чтобы определить кодировку. Для кодировок UTF-16 режим открытия файла должен быть двоичным. При наличии BOM он удаляется, а внешняя кодировка из BOM используется. Если BOM отсутствует, указанная кодировка Unicode используется как ext_enc. (Вариант кодировки с BOM нечувствителен к регистру, поэтому «bom|utf-8» также допустим.)

Параметры

opt может быть использован вместо mode для лучшей читаемости. Поддерживаются следующие ключи:

:mode

То же, что и параметр mode

:flags

Указывает флаги открытия файла как целое число. Если параметр mode задан, этот параметр будет побитово сложен.

:external_encoding

Внешняя кодировка для IO.

:internal_encoding

Внутренняя кодировка для IO. «-» — синоним для стандартной внутренней кодировки.

Если значение равно nil, преобразование не происходит.

:encoding

Указывает внешние и внутренние кодировки в формате «extern:intern».

:textmode

Если значение истинно, эквивалентно «t» в аргументе mode.

:binmode

Если значение истинно, эквивалентно «b» в аргументе mode.

:autoclose

Если значение false, то IO будет оставаться открытым после завершения работы экземпляра.

Также, opt может иметь те же ключи, что и в String#encode для управления преобразованием между внешней и внутренней кодировкой.

Пример 1

fd = IO.sysopen("/dev/tty", "w")
a = IO.new(fd,"w")
$stderr.puts "Hello"
a.puts "World"

Результат:

Hello
World

Пример 2

require 'fcntl'

fd = STDERR.fcntl(Fcntl::F_DUPFD)
io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
io.puts "Hello, World!"

fd = STDERR.fcntl(Fcntl::F_DUPFD)
io = IO.new(fd, mode: 'w', cr_newline: true,
            external_encoding: Encoding::UTF_16LE)
io.puts "Hello, World!"

Оба примера выводят «Hello, World!» в UTF-16LE в стандартный поток ошибок с преобразованием EOL, созданного puts в CR.

open(fd, mode="r" [, opt]) → io Показать исходный код
open(fd, mode="r" [, opt]) {|io| block } → obj
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;
}

Без связанного блока IO.open — синоним ::new. Если задан необязательный блок кода, он будет передан io в качестве аргумента, а объект IO будет автоматически закрыт по завершении блока. В этом случае ::open возвращает значение блока.

См. ::new для описания параметров fd, mode и opt.

pipe → [read_io, write_io] Показать исходный код
pipe(ext_enc) → [read_io, write_io]
pipe("ext_enc:int_enc" [, opt]) → [read_io, write_io]
pipe(ext_enc, int_enc [, opt]) → [read_io, write_io]
pipe(...) {|read_io, write_io| ... }
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;
    struct io_encoding_set_args ies_args;
    int fmode = 0;
    VALUE ret;

    argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
    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);

    ies_args.fptr = fptr;
    ies_args.v1 = v1;
    ies_args.v2 = v2;
    ies_args.opt = opt;
    rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
    if (state) {
        close(pipes[1]);
        io_close(r);
        rb_jump_tag(state);
    }

    args[1] = INT2NUM(pipes[1]);
    args[2] = INT2FIX(O_WRONLY);
    w = rb_protect(io_new_instance, (VALUE)args, &state);
    if (state) {
        close(pipes[1]);
        if (!NIL_P(r)) rb_io_close(r);
        rb_jump_tag(state);
    }
    GetOpenFile(w, fptr2);
    rb_io_synchronized(fptr2);

    extract_binmode(opt, &fmode);
#if DEFAULT_TEXTMODE
    if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr->mode &= ~FMODE_TEXTMODE;
        setmode(fptr->fd, O_BINARY);
    }
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
    if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
        fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
    }
#endif
#endif
    fptr->mode |= fmode;
#if DEFAULT_TEXTMODE
    if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
        fptr2->mode &= ~FMODE_TEXTMODE;
        setmode(fptr2->fd, O_BINARY);
    }
#endif
    fptr2->mode |= fmode;

    ret = rb_assoc_new(r, w);
    if (rb_block_given_p()) {
        VALUE rw[2];
        rw[0] = r;
        rw[1] = w;
        return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
    }
    return ret;
}

Создаёт пару конечных точек канала (соединённых друг с другом) и возвращает их в виде массива из двух элементов IO объектов: [ read_io, write_io ].

Если задан блок кода, то блок вызывается и возвращает значение блока. read_io и write_io передаются в блок в качестве аргументов. Если read_io и write_io не закрыты при выходе из блока, они закрываются. То есть закрытие read_io и/или write_io не вызывает ошибку.

Недоступно на всех платформах.

Если в качестве необязательного аргумента указано кодирование (имя кодирования или объект кодирования), то строка, считанная из канала, помечается указанным кодированием. Если в качестве аргумента указаны два имени кодирования, разделённые двоеточием, «A:B», то считанная строка преобразуется из кодирования A (внешнее кодирование) в кодирование B (внутреннее кодирование), а затем помечается кодированием B. Если указаны два необязательных аргумента, они должны быть объектами кодирования или именами кодирования, причём первый — внешнее кодирование, а второй — внутреннее кодирование. Если указаны внешнее и внутреннее кодирование, необязательный аргумент-хеш определяет параметры преобразования.

В примере ниже оба процесса закрывают концы канала, которыми они не пользуются. Это не просто косметический приём. Конец канала для чтения не сгенерирует условие конца файла, если есть какие-либо пишущие процессы, которые ещё используют канал. В случае родительского процесса, rd.read никогда не вернётся, если он не выполнит 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

возвращает:

Sending message to parent
Parent got: <Hi Dad>
popen([env,] cmd, mode="r" [, opt]) → io Показать исходный код
popen([env,] cmd, mode="r" [, opt]) {|io| block } → obj
static VALUE
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
{
    const char *modestr;
    VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
    int oflags, fmode;
    convconfig_t convconfig;

    if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
    if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
    switch (argc) {
      case 2:
        pmode = argv[1];
      case 1:
        pname = argv[0];
        break;
      default:
        {
            int ex = !NIL_P(opt);
            rb_error_arity(argc + ex, 1 + ex, 2 + ex);
        }
    }

    tmp = rb_check_array_type(pname);
    if (!NIL_P(tmp)) {
        long len = RARRAY_LEN(tmp);
#if SIZEOF_LONG > SIZEOF_INT
        if (len > INT_MAX) {
            rb_raise(rb_eArgError, "too many arguments");
        }
#endif
        execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE);
        RB_GC_GUARD(tmp);
    }
    else {
        SafeStringValue(pname);
        execarg_obj = Qnil;
        if (!is_popen_fork(pname))
            execarg_obj = rb_execarg_new(1, &pname, TRUE);
    }
    if (!NIL_P(execarg_obj)) {
        if (!NIL_P(opt))
            opt = rb_execarg_extract_options(execarg_obj, opt);
        if (!NIL_P(env))
            rb_execarg_setenv(execarg_obj, env);
    }
    rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
    modestr = rb_io_oflags_modestr(oflags);

    port = pipe_open(execarg_obj, 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_SET_CLASS(port, klass);
    if (rb_block_given_p()) {
        return rb_ensure(rb_yield, port, pipe_close, port);
    }
    return port;
}

Запускает указанную команду как дочерний процесс; стандартный ввод и вывод дочернего процесса будут подключены к возвращённому IO объекту.

ИД процесса запущенного процесса можно получить с помощью метода #pid.

cmd — строка или массив следующим образом.

cmd:
  "-"                                      : fork
  commandline                              : command line string which is passed to a shell
  [env, cmdname, arg1, ..., opts]          : command name and zero or more arguments (no shell)
  [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
(env and opts are optional.)

Если cmd — строка “-”, то новый экземпляр Ruby запускается как дочерний процесс.

Если cmd — массив Array String, то он будет использоваться в качестве argv дочернего процесса, минуя оболочку. Массив может содержать хеш в начале для окружения и хеш в конце для параметров, аналогично spawn.

По умолчанию режим для нового объекта файла — “r”, но mode можно установить на любой из режимов, перечисленных в описании для класса IO. Последний аргумент opt уточняет mode.

# set IO encoding
IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
  euc_jp_string = nkf_io.read
}

# merge standard output and standard error using
# spawn option.  See the document of Kernel.spawn.
IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
  ls_result_with_error = ls_io.read
}

# spawn options can be mixed with IO options
IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
  ls_result_with_error = ls_io.read
}

Вызывает исключения, которые IO.pipe и Kernel.spawn вызывают.

Если задан блок, Ruby выполнит команду как дочерний процесс, подключенный к Ruby через канал. Конец канала Ruby будет передан в качестве параметра в блок. В конце блока Ruby закроет канал и установит $?. В этом случае IO.popen вернёт значение блока.

Если блок задан с cmd «-», блок будет выполнен в двух отдельных процессах: один в родительском процессе, а другой — в дочернем. Родительский процесс получит объект канала в качестве параметра в блок, дочерний вариант блока получит nil, а стандартный ввод и стандартный вывод дочернего процесса будут подключены к родительскому через канал. Недоступно на всех платформах.

f = IO.popen("uname")
p f.readlines
f.close
puts "Parent is #{Process.pid}"
IO.popen("date") {|f| puts f.gets }
IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
p $?
IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
  f.puts "bar"; f.close_write; puts f.gets
}

возвращает:

["Linux\n"]
Parent is 21346
Thu Jan 15 22:41:19 JST 2009
21346 is here, f is #<IO:fd 3>
21352 is here, f is nil
#<Process::Status: pid 21352 exit 0>
<foo>bar;zot;
read(name, [length [, offset]] [, opt] ) → string Показать исходный код
static VALUE
rb_io_s_read(int argc, VALUE *argv, VALUE io)
{
    VALUE opt, offset;
    struct foreach_arg arg;

    argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
    open_key_args(argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    if (!NIL_P(offset)) {
        struct seek_arg sarg;
        int state = 0;
        sarg.io = arg.io;
        sarg.offset = offset;
        sarg.mode = SEEK_SET;
        rb_protect(seek_before_access, (VALUE)&sarg, &state);
        if (state) {
            rb_io_close(arg.io);
            rb_jump_tag(state);
        }
        if (arg.argc == 2) arg.argc = 1;
    }
    return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}

Открывает файл, при необходимости ищет указанный offset, затем возвращает length байт (по умолчанию — оставшуюся часть файла). read гарантирует, что файл закрывается перед возвратом.

Если name начинается с символа канала ("|"), создаётся дочерний процесс таким же образом, как в Kernel#open, и его вывод возвращается.

Параметры

Хеш параметров принимает следующие ключи:

:encoding

строка или кодирование

Указывает кодирование считываемой строки. :encoding будет проигнорирован, если указано length. См. Encoding.aliases для возможных кодирований.

:mode

строка

Указывает аргумент mode для open(). Он должен начинаться с «r», иначе это вызовет ошибку. См. ::new для списка возможных режимов.

:open_args

массив

Указывает аргументы для open() в виде массива. Этот ключ нельзя использовать совместно с :encoding или :mode.

Примеры:

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 "
IO.read("binfile", mode: "rb")   #=> "\xF7\x00\x00\x0E\x12"
readlines(name, sep=$/ [, open_args]) → array Показать исходный код
readlines(name, limit [, open_args]) → array
readlines(name, sep, limit [, open_args]) → array
static VALUE
rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
{
    VALUE opt;
    struct foreach_arg arg;
    struct getline_arg garg;

    argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
    extract_getline_args(argc-1, argv+1, &garg);
    open_key_args(argc, argv, opt, &arg);
    if (NIL_P(arg.io)) return Qnil;
    extract_getline_opts(opt, &garg);
    check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
    return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
}

Считывает весь файл, указанный по name, как отдельные строки и возвращает эти строки в массиве. Строки разделены sep.

a = IO.readlines("testfile")
a[0]   #=> "This is line one\n"

Если последний аргумент является хешем, это ключевой аргумент для open. См. IO.read для подробностей.

select(read_array [, write_array [, error_array [, timeout]]]) → array or nil Показать исходный код
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 < numberof(args.fdsets); ++i)
        rb_fd_init(&args.fdsets[i]);

    return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
}

Вызывает системный вызов select(2). Он следит за заданными массивами объектов IO, ожидает, пока один или несколько из IO объектов будут готовы к чтению, готовы к записи и имеют ожидающие исключения соответственно, и возвращает массив, содержащий массивы этих объектов IO. Он вернёт nil, если необязательное значение timeout задано, и ни один IO объект не готов в течение timeout секунд.

IO.select просматривает буфер IO объектов для проверки возможности чтения. Если буфер IO не пуст, IO.select немедленно уведомляет о возможности чтения. Эта «проверка» происходит только для IO объектов. Она не происходит для объектов, подобных IO, таких как OpenSSL::SSL::SSLSocket.

Лучший способ использовать IO.select — вызывать его после неголосующих методов, таких как read_nonblock, write_nonblock, и т. д. Эти методы поднимают исключение, которое расширяется IO::WaitReadable или IO::WaitWritable. Модули уведомляют вызывающую сторону, как ей следует ожидать с помощью IO.select. Если поднимается IO::WaitReadable, вызывающая сторона должна ожидать чтения. Если поднимается IO::WaitWritable, вызывающая сторона должна ожидать записи.

Таким образом, блокирующее чтение (readpartial) можно смоделировать, используя read_nonblock и IO.select следующим образом:

begin
  result = io_like.read_nonblock(maxlen)
rescue IO::WaitReadable
  IO.select([io_like])
  retry
rescue IO::WaitWritable
  IO.select(nil, [io_like])
  retry
end

В особенности предпочтительным является сочетание неголосующих методов и IO.select для таких объектов, как OpenSSL::SSL::SSLSocket. У него есть метод to_io для возвращения базового IO объекта. IO.select вызывает to_io для получения дескриптора файла для ожидания.

Это означает, что уведомление о возможности чтения, отправленное IO.select, не означает возможность чтения объекта OpenSSL::SSL::SSLSocket.

Наиболее вероятная ситуация — это то, что OpenSSL::SSL::SSLSocket буферирует некоторые данные. IO.select не видит буфера. Поэтому IO.select может заблокироваться, когда OpenSSL::SSL::SSLSocket#readpartial не блокируется.

Однако существует несколько более сложных ситуаций.

SSL — это протокол, представляющий собой последовательность записей. Запись состоит из нескольких байт. Таким образом, удалённая сторона SSL отправляет частичную запись, IO.select уведомляет о возможности чтения, но OpenSSL::SSL::SSLSocket не может расшифровать байт, и OpenSSL::SSL::SSLSocket#readpartial заблокируется.

Также удалённая сторона может запросить переподключение SSL, что заставляет локальный движок SSL записать некоторые данные. Это означает, что OpenSSL::SSL::SSLSocket#readpartial может вызвать системный вызов write и заблокироваться. В такой ситуации OpenSSL::SSL::SSLSocket#read_nonblock поднимает IO::WaitWritable вместо блокировки. Поэтому вызывающая сторона должна ожидать готовности к записи, как в примере выше.

Сочетание неголосующих методов и IO.select также полезно для потоков, таких как tty, сокеты каналов, когда несколько процессов читают из потока.

В заключение, разработчики ядра Linux не гарантируют, что возможность чтения, уведомлённая select(2), означает возможность чтения последующим read(2), даже для одного процесса. См. руководство select(2) в системе GNU/Linux.

Вызов IO.select до IO#readpartial работает так же, как обычно. Однако это не лучший способ использовать IO.select.

Уведомление о возможности записи, отправленное select(2), не показывает, сколько байт можно записать. Метод IO#write блокируется, пока вся заданная строка не будет записана. Поэтому IO#write(two or more bytes) может заблокироваться после того, как о возможности записи было уведомлено IO.select. IO#write_nonblock требуется, чтобы избежать блокировки.

Блокирующая запись (write) можно смоделировать, используя write_nonblock и IO.select следующим образом: IO::WaitReadable также необходимо перехватить для переподключения SSL в OpenSSL::SSL::SSLSocket.

while 0 < string.bytesize
  begin
    written = io_like.write_nonblock(string)
  rescue IO::WaitReadable
    IO.select([io_like])
    retry
  rescue IO::WaitWritable
    IO.select(nil, [io_like])
    retry
  end
  string = string.byteslice(written..-1)
end

Параметры

read_array

массив объектов IO, которые ожидают готовности к чтению

write_array

массив объектов IO, которые ожидают готовности к записи

error_array

массив объектов IO, которые ожидают исключения

timeout

числовое значение в секундах

Пример

rp, wp = IO.pipe
mesg = "ping "
100.times {
  # IO.select follows IO#read.  Not the best way to use IO.select.
  rs, ws, = IO.select([rp], [wp])
  if r = rs[0]
    ret = r.read(5)
    print ret
    case ret
    when /ping/
      mesg = "pong\n"
    when /pong/
      mesg = "ping "
    end
  end
  if w = ws[0]
    w.write(mesg)
  end
}

выводит:

ping pong
ping pong
ping pong
(snipped)
ping
sysopen(path, [mode, [perm]]) → integer Показать исходный код
static VALUE
rb_io_s_sysopen(int argc, VALUE *argv)
{
    VALUE fname, vmode, vperm;
    VALUE intmode;
    int oflags, fd;
    mode_t perm;

    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 = NUM2MODET(vperm);

    RB_GC_GUARD(fname) = rb_str_new4(fname);
    fd = rb_sysopen(fname, oflags, perm);
    return INT2NUM(fd);
}

Открывает указанный путь, возвращая базовый дескриптор файла как Integer.

IO.sysopen("testfile")   #=> 3
try_convert(obj) → io or nil Показать исходный код
static VALUE
rb_io_s_try_convert(VALUE dummy, VALUE io)
{
    return rb_io_check_io(io);
}

Попытка преобразовать obj в IO, используя метод #to_io. Возвращает преобразованный IO или nil, если obj не может быть преобразован по какой-либо причине.

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>
write(name, string [, offset]) → integer Показать исходный код
write(name, string [, offset] [, opt]) → integer
static VALUE
rb_io_s_write(int argc, VALUE *argv, VALUE io)
{
    return io_s_write(argc, argv, 0);
}

Открывает файл, при необходимости переходит к заданному offset, записывает string, затем возвращает длину записанного. write гарантирует закрытие файла перед возвратом. Если offset не задан в режиме записи, файл усекается. В противном случае, он не усекается.

IO.write("testfile", "0123456789", 20)  #=> 10
# File could contain:  "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
IO.write("testfile", "0123456789")      #=> 10
# File would now read: "0123456789"

Если последний аргумент — хэш, он задаёт параметры для внутреннего open(). Он принимает следующие ключи:

:encoding

строка или кодировка

Задает кодировку читаемой строки. См. Encoding.aliases для возможных кодировок.

:mode

строка

Задает аргумент mode для open(). Он должен начинаться с “w”, “a” или “r+”, в противном случае произойдёт ошибка. См. ::new для списка возможных режимов.

:perm

целое число

Задает аргумент perm для open().

:open_args

массив

Задает аргументы для open() в виде массива. Этот ключ не может быть использован в сочетании с другими ключами.

Публичные методы экземпляров

ios << obj → ios Показать исходный код
VALUE
rb_io_addstr(VALUE io, VALUE str)
{
    rb_io_write(io, str);
    return io;
}

Вывод строки — записывает obj в ios. obj будет преобразован в строку с использованием to_s.

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

выводит:

Hello world!
advise(advice, offset=0, len=0) → nil Показать исходный код
static VALUE
rb_io_advise(int argc, VALUE *argv, VALUE io)
{
    VALUE advice, offset, len;
    off_t off, l;
    rb_io_t *fptr;

    rb_scan_args(argc, argv, "12", &advice, &offset, &len);
    advice_arg_check(advice);

    io = GetWriteIO(io);
    GetOpenFile(io, fptr);

    off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
    l   = NIL_P(len)    ? 0 : NUM2OFFT(len);

#ifdef HAVE_POSIX_FADVISE
    return do_io_advise(fptr, advice, off, l);
#else
    ((void)off, (void)l);       /* Ignore all hint */
    return Qnil;
#endif
}

Объявляет намерение получить доступ к данным из текущего файла по определенному шаблону. На платформах, которые не поддерживают системный вызов posix_fadvise(2), этот метод является бесполезным.

advice — одно из следующих символов:

:normal

Не выдается никаких советов; стандартное предположение для открытого файла.

:sequential

Данные будут читаться последовательно, с чтением меньших смещений перед большими.

:random

Данные будут читаться в произвольном порядке.

:willneed

Данные будут обработаны в ближайшем будущем.

:dontneed

Данные не будут обработаны в ближайшем будущем.

:noreuse

Данные будут обработаны только один раз.

Семантика совета зависит от платформы. Подробности см. в man 2 posix_fadvise.

«Данные» означают область текущего файла, начинающуюся со смещения offset и продолжающуюся len байт. Если len равно 0, область заканчивается в последнем байте файла. По умолчанию как offset, так и len равны 0, что означает, что совет относится ко всему файлу.

Если произошла ошибка, будет возбуждено одно из следующих исключений:

IOError

Поток IO закрыт.

Errno::EBADF

Дескриптор файла текущего файла недействителен.

Errno::EINVAL

Было задано недопустимое значение для advice.

Errno::ESPIPE

Дескриптор файла текущего файла относится к FIFO или каналу. (Linux поднимает Errno::EINVAL в этом случае).

TypeError

Либо advice не был символом, либо один из других аргументов не был Integer.

RangeError

Один из заданных аргументов был слишком большим/маленьким.

Этот список неполный; возможны и другие исключения Errno

.

autoclose = bool → true or false Показать исходный код
static VALUE
rb_io_set_autoclose(VALUE io, VALUE autoclose)
{
    rb_io_t *fptr;
    GetOpenFile(io, fptr);
    if (!RTEST(autoclose))
        fptr->mode |= FMODE_PREP;
    else
        fptr->mode &= ~FMODE_PREP;
    return io;
}

Устанавливает флаг автоматического закрытия.

f = open("/dev/null")
IO.for_fd(f.fileno)
# ...
f.gets # may cause IOError

f = open("/dev/null")
IO.for_fd(f.fileno).autoclose = true
# ...
f.gets # won't cause IOError
autoclose? → true or false Показать исходный код
static VALUE
rb_io_autoclose_p(VALUE io)
{
    rb_io_t *fptr = RFILE(io)->fptr;
    rb_io_check_closed(fptr);
    return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
}

Возвращает true если базовый дескриптор файла ios будет закрыт автоматически при финализации, в противном случае false.

beep() Показать исходный код
static VALUE
console_beep(VALUE io)
{
    rb_io_t *fptr;
    int fd;

    GetOpenFile(io, fptr);
    fd = GetWriteFD(fptr);
#ifdef _WIN32
    (void)fd;
    MessageBeep(0);
#else
    if (write(fd, "\a", 1) < 0)
        rb_sys_fail(0);
#endif
    return io;
}
binmode → ios Показать исходный код
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;
}

Переводит ios в двоичный режим. После перевода потока в двоичный режим, он не может быть переведен обратно в текстовый.

  • преобразование новой строки отключено

  • преобразование кодировки отключено

  • содержимое обрабатывается как ASCII-8BIT

binmode? → true or false Показать исходный код
static VALUE
rb_io_binmode_p(VALUE io)
{
    rb_io_t *fptr;
    GetOpenFile(io, fptr);
    return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
}

Возвращает true если ios находится в двоичном режиме.

bytes() Показать исходный код
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);
}

Это устаревший псевдоним для each_byte.

chars() Показать исходный код
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);
}

Это устаревший псевдоним для each_char.

close → nil Показать исходный код
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;
}

Закрывает ios и сбрасывает все ожидаемые записи в операционную систему. Поток недоступен для любых дальнейших операций с данными; попытка вызовет IOError. Потоки ввода-вывода автоматически закрываются при их взятии сборщиком мусора.

Если ios открыт IO.popen, close устанавливает $?.

Вызов этого метода для закрытого объекта IO просто игнорируется с Ruby 2.3.

close_on_exec = bool → true or false Показать исходный код
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;
}

Устанавливает флаг закрытия при выполнении.

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 устанавливает флаги закрытия при выполнении для всех дескрипторов файлов по умолчанию с Ruby 2.0.0. Поэтому устанавливать их самостоятельно не требуется. Кроме того, сброс флага закрытия при выполнении может привести к утечке дескриптора файла, если другой поток использует fork() и exec() (например, через метод system()). Если действительно требуется наследование дескриптора файла дочернему процессу, используйте аргументы spawn() такие как fd=>fd.

close_on_exec? → true or 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;
}

Возвращает true если ios будет закрыт при выполнении.

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
close_read → nil Показать исходный код
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);
}

Закрывает читаемую часть дуплексного потока ввода-вывода (то есть потока, содержащего как входной, так и выходной поток, например, канала). Вызовет IOError если поток не дуплексный.

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

выводит:

prog.rb:3:in `readlines': not opened for reading (IOError)
 from prog.rb:3
close_write → nil Показать исходный код
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;
}

Закрывает записываемую часть дуплексного потока ввода-вывода (то есть потока, содержащего как входной, так и выходной поток, например, канала). Вызовет IOError если поток не дуплексный.

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

выводит:

prog.rb:3:in `write': not opened for writing (IOError)
 from prog.rb:3:in `print'
 from prog.rb:3
closed? → true or false Показать исходный код
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;
}

Возвращает true если ios полностью закрыт (для дуплексных потоков, как читатель, так и записыватель), 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
codepoints() Показать исходный код
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);
}

Это устаревший псевдоним для each_codepoint.

cooked {|io| } Показать исходный код
static VALUE
console_cooked(VALUE io)
{
    return ttymode(io, rb_yield, set_cookedmode, NULL);
}

Возвращает self в режиме подготовленного ввода.

STDIN.cooked(&:gets)

будет читать и возвращать строку с эхом и редактированием строк.

Для использования этого метода необходимо подключить 'io/console'.

cooked! Показать исходный код
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;
}

Включает режим подготовленного ввода.

Если требуется вернуть режим терминала, используйте io.cooked { … }.

Для использования этого метода необходимо подключить 'io/console'.

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

Выполняет блок для каждой строки в ios, где строки разделены sep. ios должен быть открыт для чтения, иначе будет поднято исключение IOError.

Если блок не указан, возвращается перечислитель.

f = File.new("testfile")
f.each {|line| puts "#{f.lineno}: #{line}" }

результат:

1: This is line one
2: This is line two
3: This is line three
4: And so on...
each_byte {|byte| block } → ios Показать исходный код
each_byte → an_enumerator
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;
}

Вызывает указанный блок один раз для каждого байта (0..255) в ios, передавая байт в качестве аргумента. Поток должен быть открыт для чтения, иначе будет поднято исключение IOError.

Если блок не указан, возвращается перечислитель.

f = File.new("testfile")
checksum = 0
f.each_byte {|x| checksum ^= x }   #=> #<File:testfile>
checksum                           #=> 12
each_char {|c| block } → ios Показать исходный код
each_char → an_enumerator
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;
}

Вызывает указанный блок один раз для каждого символа в ios, передавая символ в качестве аргумента. Поток должен быть открыт для чтения, иначе будет поднято исключение IOError.

Если блок не указан, возвращается перечислитель.

f = File.new("testfile")
f.each_char {|c| print c, ' ' }   #=> #<File:testfile>
each_codepoint {|c| block } → ios Показать исходный код
codepoints {|c| block } → ios
each_codepoint → an_enumerator
codepoints → an_enumerator
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;
}

Передает порядковый номер кода каждого символа в ios, передавая код в качестве аргумента. Поток должен быть открыт для чтения, иначе будет поднято исключение IOError.

Если блок не указан, возвращается перечислитель.

each_line(sep=$/) {|line| block } → ios Показать исходный код
each_line(limit) {|line| block } → ios
each_line(sep, limit) {|line| block } → ios
each_line(...) → an_enumerator
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;
}

Выполняет блок для каждой строки в ios, где строки разделены sep. ios должен быть открыт для чтения, иначе будет поднято исключение IOError.

Если блок не указан, возвращается перечислитель.

f = File.new("testfile")
f.each {|line| puts "#{f.lineno}: #{line}" }

результат:

1: This is line one
2: This is line two
3: This is line three
4: And so on...
echo = flag Показать исходный код
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;
}

Включает/отключает отображение ввода. На некоторых платформах все комбинации этих флагов и режимов raw/cooked могут быть недопустимы.

Для использования этого метода необходимо подключить 'io/console'.

echo? → true or false Показать исходный код
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;
}

Возвращает true, если отображение ввода включено.

Для использования этого метода необходимо подключить 'io/console'.

eof → true or false Показать исходный код
eof? → true or false
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;
}

Возвращает true, если ios достиг конца файла, т.е. больше нет данных для чтения. Поток должен быть открыт для чтения, иначе будет поднято исключение 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 (которое недоступно для некоторых потоков).

eof? → true or false Показать исходный код
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;
}

Возвращает true, если ios достиг конца файла, т.е. больше нет данных для чтения. Поток должен быть открыт для чтения, иначе будет поднято исключение 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 (которое недоступно для некоторых потоков).

IO#expect(pattern,timeout=9999999) → Array Показать исходный код
IO#expect(pattern,timeout=9999999) { |result| ... } → nil
# 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

Читает из IO до тех пор, пока заданный pattern не совпадёт или время ожидания не закончится.

Возвращает массив со считанным буфером, за которым следуют совпадения. Если указан блок, результат передаётся в блок, и возвращается nil.

Без блока он ожидает, пока вход, соответствующий заданному pattern, не будет получен из IO, или не истечёт указанное время ожидания. Возвращает массив, когда шаблон получен из IO. Первый элемент массива - вся строка, полученная из IO до совпадения шаблона, за которым следуют элементы, указывающие на совпавший шаблон в регулярном выражении.

Необязательный параметр time определяет общее время ожидания шаблона в секундах. Если время ожидания истечёт или обнаружен конец файла, возвращается или передаётся nil. Однако буфер в режиме ожидания сохраняется для следующего вызова expect. Значение по умолчанию для времени ожидания - 9999999 секунд.

external_encoding → encoding Показать исходный код
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));
}

Возвращает объект Encoding, представляющий кодировку файла. Если io находится в режиме записи и кодировка не указана, возвращает nil.

fcntl(integer_cmd, arg) → integer Показать исходный код
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);
}

Предоставляет механизм для выдачи низкоуровневых команд для управления или запроса потоков ввода-вывода, ориентированных на файлы. Аргументы и результаты зависят от платформы. Если arg - это число, его значение передаётся напрямую. Если это строка, она интерпретируется как двоичная последовательность байтов (Array#pack может быть полезным способом построения этой строки). На платформах Unix см. fcntl(2) для подробностей. Не реализовано на всех платформах.

fdatasync → 0 or nil Показать исходный код
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);
}

Немедленно записывает все буферизованные данные в ios на диск.

Если подлежащая операционная система не поддерживает fdatasync(2), вызывается IO#fsync (что может вызвать исключение NotImplementedError).

fileno → integer Показать исходный код
to_i → integer
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);
}

Возвращает целое число, представляющее числовой дескриптор файла для ios.

$stdin.fileno    #=> 0
$stdout.fileno   #=> 1
Также алиасируется как: to_i
flush → ios Показать исходный код
VALUE
rb_io_flush(VALUE io)
{
    return rb_io_flush_raw(io, 1);
}

Очищает любые буферизованные данные в ios в базовой операционной системе (обратите внимание, что это буферизация только Ruby; ОС может также буферизовать данные).

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

выводит:

no newline
fsync → 0 or nil Показать исходный код
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);
}

Немедленно записывает все буферизованные данные в ios на диск. Обратите внимание, что fsync отличается от использования IO#sync=. Последнее гарантирует, что данные очищаются из буферов Ruby, но не гарантирует, что базовая операционная система фактически запишет их на диск.

NotImplementedError генерируется, если базовая операционная система не поддерживает fsync(2).

getbyte → integer or nil Показать исходный код
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);
}

Получает следующий 8-битный байт (0..255) из ios. Возвращает nil при вызове в конце файла.

f = File.new("testfile")
f.getbyte   #=> 84
f.getbyte   #=> 104
getc → string or nil Показать исходный код
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);
}

Считывает строку из одного символа из ios. Возвращает nil при вызове в конце файла.

f = File.new("testfile")
f.getc   #=> "h"
f.getc   #=> "e"
getch(min: nil, time: nil) → char Показать исходный код
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);
}

Считывает и возвращает символ в сыром режиме.

Для использования этого метода необходимо подключить 'io/console'.

getpass(prompt=nil) → string Показать исходный код
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);
}

Считывает и возвращает строку без отображения ввода. Выводит prompt , если не nil.

Для использования этого метода необходимо подключить 'io/console'.

gets(sep=$/) → string or nil Показать исходный код
gets(limit) → string or nil
gets(sep, limit) → string or nil
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;
}

Считывает следующую «строку» из потока ввода/вывода; строки разделяются символом 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"
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 Показать исходный код
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;
}

Очищает буфер ввода в ядре.

Для использования этого метода необходимо подключить 'io/console'.

inspect → string Показать исходный код
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, ">");
}

Возвращает строку, описывающую этот объект IO.

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

Возвращает Encoding внутренней строки, если указано преобразование. В противном случае возвращает nil.

ioctl(integer_cmd, arg) → integer Показать исходный код
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);
}

Предоставляет механизм для выдачи команд низкого уровня для управления или запроса устройств ввода/вывода. Аргументы и результаты зависят от платформы. Если arg является числом, его значение передается непосредственно. Если это строка, она интерпретируется как двоичная последовательность байтов. На платформах Unix см. ioctl(2) для получения подробной информации. Не реализовано на всех платформах.

ioflush Показать исходный код
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;
}

Очищает буферы ввода и вывода в ядре.

Для использования этого метода необходимо подключить 'io/console'.

isatty → true or false Показать исходный код
static VALUE
rb_io_isatty(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (isatty(fptr->fd) == 0)
        return Qfalse;
    return Qtrue;
}

Возвращает true если ios связан с устройством терминала (tty), false в противном случае.

File.new("testfile").isatty   #=> false
File.new("/dev/tty").isatty   #=> true
lineno → integer Показать исходный код
static VALUE
rb_io_lineno(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    rb_io_check_char_readable(fptr);
    return INT2NUM(fptr->lineno);
}

Возвращает текущий номер строки в ios. Поток должен быть открыт для чтения. lineno подсчитывает количество вызовов gets, а не количество найденных символов новой строки. Два значения будут различаться, если gets вызывается с разделителем, отличным от новой строки.

Методы, использующие $/ , такие как each, lines и 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
lineno = integer → integer Показать исходный код
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;
}

Вручную устанавливает текущий номер строки на заданное значение. $. обновляется только при следующем чтении.

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
lines(*args) Показать исходный код
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);
}

Это устаревший алиас для each_line.

noecho {|io| } Показать исходный код
static VALUE
console_noecho(VALUE io)
{
    return ttymode(io, rb_yield, set_noecho, NULL);
}

Возвращает self с отключенным отображением ввода.

STDIN.noecho(&:gets)

будет считывать и возвращать строку без отображения ввода.

Для использования этого метода необходимо подключить 'io/console'.

nonblock {|io| } → io Показать исходный код
nonblock(boolean) {|io| } → io
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);
}

Возвращает self в режиме без блокировки.

Если false передаётся в качестве аргумента, self возвращается в режиме блокировки. Исходный режим восстанавливается после выполнения блока.

nonblock = boolean → boolean Показать исходный код
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;
}

Включает режим неблокирующего ввода-вывода на потоке, если значение равно true, и режим блокирующего ввода-вывода, если равно false.

nonblock? → boolean Показать исходный код
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;
}

Возвращает true, если объект IO находится в режиме неблокирующего ввода-вывода.

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 Показать исходный код
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;
}

Очищает буфер вывода в ядре.

Для использования этого метода необходимо подключить модуль 'io/console'.

pathconf(p1) Показать исходный код
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);
}

Возвращает переменную конфигурации имени файла с использованием fpathconf().

name должно быть константой из Etc, которая начинается с PC_.

Возвращаемое значение — целое число или nil. nil означает неопределённый предел. (fpathconf() возвращает -1, но errno не устанавливается.)

require 'etc'
IO.pipe {|r, w|
  p w.pathconf(Etc::PC_PIPE_BUF) #=> 4096
}
pid → integer Показать исходный код
static VALUE
rb_io_pid(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (!fptr->pid)
        return Qnil;
    return PIDT2NUM(fptr->pid);
}

Возвращает идентификатор процесса дочернего процесса, связанного с ios. Он будет установлен методом IO.popen.

pipe = IO.popen("-")
if pipe
  $stderr.puts "In parent, child pid is #{pipe.pid}"
else
  $stderr.puts "In child, pid is #{$$}"
end

возвращает:

In child, pid is 26209
In parent, child pid is 26209
pos → integer Показать исходный код
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);
}

Возвращает текущий смещение (в байтах) объекта ios.

f = File.new("testfile")
f.pos    #=> 0
f.gets   #=> "This is line one\n"
f.pos    #=> 17
pos = integer → integer Показать исходный код
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);
}

Перемещает указатель к заданной позиции (в байтах) в ios. Не гарантируется точное достижение позиции, если ios в текстовом режиме.

f = File.new("testfile")
f.pos = 17
f.gets   #=> "This is line two\n"
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
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;
}

Записывает заданный объект(ы) в ios. Возвращает nil.

Поток должен быть открыт для записи. Каждый объект, который не является строкой, будет преобразован путём вызова метода to_s. Если вызов без аргументов, выводит содержимое $_.

Если разделитель полей вывода ($,) не nil, он вставляется между объектами. Если разделитель записей вывода ($\) не nil, он добавляется в конец вывода.

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

возвращает:

This is 100 percent.
printf(format_string [, obj, ...]) → nil Показать исходный код
VALUE
rb_io_printf(int argc, const VALUE *argv, VALUE out)
{
    rb_io_write(out, rb_f_sprintf(argc, argv));
    return Qnil;
}

Форматирует и записывает в ios, преобразуя параметры в соответствии со строкой формата. См. Kernel#sprintf для подробностей.

putc(obj) → obj Показать исходный код
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;
}

Если obj — Numeric, записывает символ, код которого — младший байт obj, иначе записывает первый байт строкового представления obj в ios. Примечание: Этот метод небезопасен для использования с многобайтовыми символами, так как они будут усечены.

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

возвращает:

AA
puts(obj, ...) → nil Показать исходный код
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;
}

Записывает заданный объект(ы) в ios. Добавляет символ новой строки после объектов, которые его не содержат. Возвращает nil.

Поток должен быть открыт для записи. Если в качестве аргумента передан массив, каждый элемент записывается на новой строке. Каждый объект, который не является строкой или массивом, преобразуется путём вызова метода to_s. Если вызов без аргументов, выводит только символ новой строки.

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

возвращает:

this
is
a
test

Обратите внимание, что puts всегда использует новые строки и не зависит от разделителя записей вывода ($\).

raw(min: nil, time: nil) {|io| } Показать исходный код
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);
}

Возвращает self в режиме «raw».

STDIN.raw(&:gets)

будет читать и возвращать строку без отображения ввода и редактирования.

Для использования этого метода необходимо подключить модуль 'io/console'.

raw!(min: nil, time: nil) Показать исходный код
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;
}

Включает режим «raw».

Если требуется вернуть режим терминала, используйте io.raw { … }.

Для использования этого метода необходимо подключить модуль 'io/console'.

read([length [, outbuf]]) → string, outbuf, or nil Показать исходный код
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;
}

Считывает length байтов из потока ввода-вывода.

length должно быть неотрицательным целым числом или nil.

Если length — положительное целое число, read пытается прочитать length байтов без преобразования (бинарный режим). Он возвращает nil, если при чтении обнаружен конец файла (EOF). Меньше length байтов возвращается, если EOF обнаружен во время чтения. В случае целочисленного length, возвращаемая строка всегда в кодировке ASCII-8BIT.

Если length опущен или равен nil, считывание выполняется до конца файла (EOF) и применяется преобразование кодировки, если необходимо. Строка возвращается, даже если EOF обнаружен до чтения каких-либо данных.

Если length равен нулю, возвращается пустая строка ("").

Если присутствует необязательный аргумент outbuf, он должен ссылаться на строку, которая получит данные. В outbuf будут содержаться только полученные данные после вызова метода, даже если она не была пустой вначале.

При вызове этого метода в конце файла, он возвращает nil или "", в зависимости от length: read, read(nil), и read(0) возвращают "", read(positive_integer) возвращает nil.

f = File.new("testfile")
f.read(16)   #=> "This is line one"

# read whole file
open("file") do |f|
  data = f.read   # This returns a string even if the file is empty.
  # ...
end

# iterate over fixed length records
open("fixed-record-file") do |f|
  while record = f.read(256)
    # ...
  end
end

# iterate over variable length records,
# each record is prefixed by its 32-bit length
open("variable-record-file") do |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
end

Обратите внимание, что этот метод ведёт себя как функция fread() в C. Это означает, что он повторно пытается вызвать системные вызовы read(2) для чтения данных с заданной длиной (или до EOF). Это поведение сохраняется, даже если ios находится в режиме неблокирующего ввода-вывода. (Этот метод нечувствителен к флагу неблокирующего ввода-вывода, как и другие методы.) Если вам нужно поведение как единого системного вызова read(2), рассмотрите readpartial, read_nonblock и sysread.

read_nonblock(maxlen [, options]) → string Показать исходный код
read_nonblock(maxlen, outbuf [, options]) → outbuf
# File prelude.rb, line 75
def read_nonblock(len, buf = nil, exception: true)
  __read_nonblock(len, buf, exception)
end

Читает не более maxlen байтов из ios, используя системный вызов read(2) после установки O_NONBLOCK для соответствующего дескриптора файла.

Если необязательный аргумент outbuf присутствует, он должен ссылаться на строку, которая получит данные. outbuf будет содержать только полученные данные после вызова метода, даже если он не был пустым вначале.

#read_nonblock просто вызывает системный вызов read(2). Он вызывает все ошибки, которые может вызвать системный вызов read(2): Errno::EWOULDBLOCK, Errno::EINTR и т.д. Приложение должно обрабатывать эти ошибки.

Если возникает исключение Errno::EWOULDBLOCK или Errno::EAGAIN, оно дополняется IO::WaitReadable. Поэтому IO::WaitReadable можно использовать для перехвата исключений и повторной попытки read_nonblock.

#read_nonblock вызывает EOFError при достижении конца файла.

Если буфер считанных байтов не пуст, #read_nonblock считывает из буфера, как readpartial. В этом случае системный вызов read(2) не вызывается.

Когда #read_nonblock генерирует исключение типа IO::WaitReadable, #read_nonblock не должен вызываться, пока io не станет доступным для чтения, чтобы избежать бесконечного цикла. Это можно сделать следующим образом.

# 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, за исключением того, что устанавливается флаг неблокирующего режима.

Указав ключевой аргумент exception в false, вы можете указать, что #read_nonblock не должен генерировать исключение IO::WaitReadable, а вместо этого должен возвращать символ :wait_readable. При достижении конца файла он будет возвращать nil вместо генерации EOFError.

readbyte → integer Показать исходный код
static VALUE
rb_io_readbyte(VALUE io)
{
    VALUE c = rb_io_getbyte(io);

    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}

Читает байт аналогично IO#getbyte, но генерирует исключение EOFError при достижении конца файла.

readchar → string Показать исходный код
static VALUE
rb_io_readchar(VALUE io)
{
    VALUE c = rb_io_getc(io);

    if (NIL_P(c)) {
        rb_eof_error();
    }
    return c;
}

Читает строку длиной в один символ из ios. Генерирует исключение EOFError при достижении конца файла.

f = File.new("testfile")
f.readchar   #=> "h"
f.readchar   #=> "e"
readline(sep=$/) → string Показать исходный код
readline(limit) → string
readline(sep, limit) → string
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;
}

Читает строку, как с IO#gets, но генерирует исключение EOFError при достижении конца файла.

readlines(sep=$/) → array Показать исходный код
readlines(limit) → array
readlines(sep, limit) → array
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);
}

Читает все строки из ios и возвращает их в anArray. Строки разделяются необязательным sep. Если sep является nil, вся оставшаяся часть потока возвращается как один элемент. Если первый аргумент является целым числом или задан необязательный второй аргумент, возвращаемая строка не будет длиннее заданного значения в байтах. Поток должен быть открыт для чтения, иначе будет вызвано исключение IOError.

f = File.new("testfile")
f.readlines[0]   #=> "This is line one\n"
readpartial(maxlen) → string Показать исходный код
readpartial(maxlen, outbuf) → outbuf
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;
}

Читает не более maxlen байтов из потока ввода-вывода. Он блокируется только если ios не имеет данных, немедленно доступных для чтения. Не блокируется, если данные есть.

Если необязательный аргумент outbuf присутствует, он должен ссылаться на строку, которая получит данные. outbuf будет содержать только полученные данные после вызова метода, даже если он не был пустым вначале.

Генерирует исключение EOFError при достижении конца файла.

readpartial предназначен для потоков, таких как pipe, сокет, tty и т.п. Он блокируется только при отсутствии немедленно доступных данных. Это означает, что он блокируется только в тех случаях, когда выполняются все следующие условия.

  • буфер байтов в объекте IO пуст.

  • содержимое потока пусто.

  • поток еще не достиг EOF.

Когда readpartial блокируется, он ожидает данные или 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 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"     ""              ""

Обратите внимание, что readpartial ведет себя аналогично sysread. Различия:

  • Если буфер байтов не пуст, считывается из буфера байтов вместо «sysread для буферизованного IO (IOError)».

  • Он не вызывает Errno::EWOULDBLOCK и Errno::EINTR. Если readpartial встречает EWOULDBLOCK и EINTR в системном вызове read, readpartial повторяет системный вызов.

Это означает, что readpartial нечувствителен к флагу неблокирующего режима. Он блокируется в ситуации, когда #sysread вызывает Errno::EWOULDBLOCK, как если бы fd был в режиме блокировки.

ready? → true, false or 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;
}

Возвращает true, если данные доступны для чтения без блокировки, или false. Возвращает nil, если нет доступной информации.

reopen(other_IO) → ios Показать исходный код
reopen(path, mode_str) → ios
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;
}

Переустанавливает ассоциацию ios с потоком ввода-вывода, указанным в other_IO, или с новым потоком, открытым по пути path. Это может динамически изменить фактический класс этого потока.

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"
rewind → 0 Показать исходный код
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);
}

Устанавливает позицию 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"

Обратите внимание, что его нельзя использовать с потоками, такими как pipes, ttys и сокеты.

scanf(str) { |current_match| ... } Показать исходный код
# 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

Сканирует текущую строку до тех пор, пока соответствие не исчерпается, возвращая каждое соответствие по мере его обнаружения в строке. Блок не требуется, так как результаты просто будут агрегированы в конечный массив.

"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.

seek(amount, whence=IO::SEEK_SET) → 0 Показать исходный код
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);
}

Перемещает указатель в потоке на заданное смещение anInteger в соответствии со значением whence:

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

Если указан единственный аргумент, строка, считанная из io, помечается указанным кодированием. Если кодирование — это два имени кодирования, разделённые двоеточием «A:B», считанная строка преобразуется из кодирования A (внешнее кодирование) в кодирование B (внутреннее кодирование), а затем помечается кодированием B. Если указаны два аргумента, они должны быть объектами кодирования или именами кодирования, причём первый — внешнее кодирование, а второй — внутреннее кодирование. Если внешнее и внутреннее кодирование указаны, необязательный аргумент хэш задаёт опции преобразования.

stat → stat Показать исходный код
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);
}

Возвращает информацию о статусе 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
sync → true или 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;
}

Возвращает текущий режим «синхронизации» ios. Когда режим синхронизации включён, весь вывод немедленно передаётся в операционную систему и не буферизуется Ruby. См. также IO#fsync.

f = File.new("testfile")
f.sync   #=> false
sync = boolean → boolean Показать исходный код
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;
}

Устанавливает режим «синхронизации» в true или false. Когда режим синхронизации включён, весь вывод немедленно передаётся в операционную систему и не буферизуется внутри. Возвращает новое состояние. См. также IO#fsync.

f = File.new("testfile")
f.sync = true
sysread(maxlen[, outbuf]) → строка Показать исходный код
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;
}

Считывает maxlen байтов из ios с помощью низкоуровневого чтения и возвращает их как строку. Не смешивайте с другими методами, которые считывают данные из ios, иначе могут возникнуть непредсказуемые результаты.

Если необязательный аргумент outbuf присутствует, он должен ссылаться на строку, которая получит данные. outbuf будет содержать только полученные данные после вызова метода, даже если она не была пустой в начале.

Возвращает SystemCallError при ошибке и EOFError в конце файла.

f = File.new("testfile")
f.sysread(16)   #=> "This is line one"
sysseek(offset, whence=IO::SEEK_SET) → целое число Показать исходный код
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);
}

Перемещает указатель на заданный offset в потоке в соответствии со значением whence (см. IO#seek для значений whence). Возвращает новый смещение в файле.

f = File.new("testfile")
f.sysseek(-13, IO::SEEK_END)   #=> 53
f.sysread(10)                  #=> "And so on."
syswrite(строка) → целое число Показать исходный код
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);
}

Записывает заданную строку в ios с помощью низкоуровневого записи. Возвращает количество записанных байтов. Не смешивайте с другими методами, которые записывают данные в ios, иначе могут возникнуть непредсказуемые результаты. Возвращает SystemCallError при ошибке.

f = File.new("out", "w")
f.syswrite("ABCDEF")   #=> 6
tell → целое число Показать исходный код
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);
}

Возвращает текущее смещение (в байтах) ios.

f = File.new("testfile")
f.pos    #=> 0
f.gets   #=> "This is line one\n"
f.pos    #=> 17
to_i()
Псевдоним для: fileno
to_io → ios Показать исходный код
static VALUE
rb_io_to_io(VALUE io)
{
    return io;
}

Возвращает ios.

tty? → true или false Показать исходный код
static VALUE
rb_io_isatty(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (isatty(fptr->fd) == 0)
        return Qfalse;
    return Qtrue;
}

Возвращает true если ios связан с устройством терминала (tty), false в противном случае.

File.new("testfile").isatty   #=> false
File.new("/dev/tty").isatty   #=> true
ungetbyte(строка) → nil
ungetbyte(целое число) → nil
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;
}

Возвращает байты (переданные в качестве параметра) в ios, таким образом, последующее буферизованное чтение вернёт их. Только один байт может быть возвращён обратно перед последующей операцией чтения (то есть, вы сможете прочитать только последний из нескольких байтов, которые были возвращены обратно). Не имеет эффекта при небуферизованном чтении (таком как IO#sysread).

f = File.new("testfile")   #=> #<File:testfile>
b = f.getbyte              #=> 0x38
f.ungetbyte(b)             #=> nil
f.getbyte                  #=> 0x38
ungetc(строка) → nil Показать исходный код
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;
}

Возвращает один символ (переданный в качестве параметра) в ios, таким образом, последующее буферизованное чтение символов вернёт его. Только один символ может быть возвращён обратно перед последующей операцией чтения (то есть, вы сможете прочитать только последний из нескольких символов, которые были возвращены обратно). Не имеет эффекта при небуферизованном чтении (таком как IO#sysread).

f = File.new("testfile")   #=> #<File:testfile>
c = f.getc                 #=> "8"
f.ungetc(c)                #=> nil
f.getc                     #=> "8"
wait(timeout = nil, mode = :read) → IO, true или nil Показать исходный код
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;
}

Ожидает, пока IO будет читаемым или записываемым без блокирования и возвращает self, или nil при истечении времени ожидания. Возвращает true немедленно, когда доступны буферизованные данные. Необязательный параметр mode является одним из :read, :write, или :read_write.

wait_readable → IO, true или nil
wait_readable(timeout) → IO, true или nil
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;
}

Ожидает, пока IO будет читаемым без блокирования и возвращает self, или nil при истечении времени ожидания. Возвращает true немедленно, когда доступны буферизованные данные.

wait_writable → IO
wait_writable(timeout) → IO или nil
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;
}

Ожидает, пока IO будет записываемым без блокирования и возвращает self или nil при истечении времени ожидания.

winsize → [строки, колонки] Показать исходный код
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)));
}

Возвращает размер консоли.

Для использования этого метода необходимо подключить 'io/console'.

winsize = [строки, колонки] Показать исходный код
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;
}

Пытается установить размер консоли. Эффект зависит от платформы и среды выполнения.

Для использования этого метода необходимо подключить 'io/console'.

write(строка) → целое число Показать исходный код
static VALUE
io_write_m(VALUE io, VALUE str)
{
    return io_write(io, str, 0);
}

Записывает заданную строку в ios. Поток должен быть открыт для записи. Если аргумент не является строкой, он будет преобразован в строку с использованием to_s. Возвращает количество записанных байтов.

count = $stdout.write("This is a test\n")
puts "That was #{count} bytes of data"

выводит:

This is a test
That was 15 bytes of data
write_nonblock(string) → integer Показать исходный код
write_nonblock(string [, options]) → integer
# File prelude.rb, line 133
def write_nonblock(buf, exception: true)
  __write_nonblock(buf, exception)
end

Записывает заданную строку в ios с помощью системного вызова write(2) после установки O_NONBLOCK для базового дескриптора файла.

Возвращает количество записанных байт.

#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, #write_nonblock не поддерживается в зависимости от типа объекта IO. В таких случаях #write_nonblock вызывает Errno::EBADF.

Указав ключевой аргумент exception в false, можно указать, что #write_nonblock не должен вызывать исключение IO::WaitWritable, а вместо этого должен возвращать символ :wait_writable.

Закрытые методы экземпляра

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

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API