) принимает до четырех параметров. Первый из них — массив дескрипторов для чтения, а остальные три необязательны (массив дескрипторов для записи, дескрипторов для ошибок и величина тайм-аута). Если на каком-то из устройств, дескрипторы которых заданы в первом массиве, оказываются новые данные для чтения или какое-то из устройств, дескрипторы которых перечислены во втором массиве, готово к выполнению записи, метод возвращает массив из трех элементов, каждый из которых в свою очередь является массивом, где указаны дескрипторы устройств, готовых
к выполнению ввода/вывода.
Метод
syscall
из модуля
Kernel
принимает по меньшей мере один целочисленный параметр (а всего до девяти целочисленных или строковых параметров). Первый параметр определяет выполняемую операцию ввода/вывода.
Метод
fileno
возвращает обычный файловый дескриптор, ассоциированный с потоком ввода/вывода. Это наименее системно зависимый из всех перечислениях выше методов.
desc = $stderr.fileno # 2
10.1.15. Неблокирующий ввод/вывод
«За кулисами» Ruby предпринимает согласованные меры, чтобы операции ввода/вывода не блокировали выполнение программы. В большинстве случаев для управления вводом/выводом можно пользоваться потоками — один поток может выполнить блокирующую операцию, а второй будет продолжать работу.
Это немного противоречит интуиции. Потоки Ruby работают в том же процессе, они не являются платформенными потоками. Быть может, вам кажется, что блокирующая операция ввода/вывода должна приостанавливать весь процесс, а значит, и все его потоки. Это не так — Ruby аккуратно управляет вводом/выводом прозрачно для программиста.
Но если вы все же хотите включить неблокирующий режим ввода/вывода, такая возможность есть. Небольшая библиотека
io/nonblock
предоставляет методы чтения и установки для объекта
появился сравнительно недавно с целью упростить ввод/вывод при определенных условиях. Он может использоваться с любыми потоками, например с сокетами.
Параметр «максимальная длина» (max length) обязателен. Если задан параметр buffer, то он должен ссылаться на строку, в которой будут храниться данные.
data = sock.readpartial(128) #
Читать не более 128 байтов.
Метод
readpartial
игнорирует установленный режим блокировки ввода/вывода. Он может блокировать программу, но лишь при выполнении следующих условий: буфер объекта IO пуст, в потоке ничего нет и поток еще не достиг конца файла.
Таким образом, если в потоке есть данные, то
readpartial
не будет блокировать программу. Он читает не более указанного числа байтов, а если байтов оказалось меньше, то прочитает их и продолжит выполнение.
Если в потоке нет данных, но при этом достигнут конец файла, то
readpartial
немедленно возбуждает исключение
EOFError
.
Если вызов блокирующий, то он ожидает, пока не произойдет одно из двух событий: придут новые данные или обнаружится конец файла. Если поступают данные, метод возвращает их вызывающей программе, а в случае обнаружения конца файла возбуждает исключение
EOFError
.
При вызове метода
sysread
в блокирующем режиме он ведет себя похоже на
readpartial
. Если буфер пуст, их поведение вообще идентично.
10.1.17. Манипулирование путевыми именами
Основными методами для работы с путевыми именами являются методы класса
File.dirname
и
File.basename
; они работают, как одноименные команды UNIX, то есть возвращают имя каталога и имя файла соответственно. Если вторым параметром методу
basename
передана строка с расширением имени файла, то это расширение исключается.
str = "/home/dave/podbay.rb"
dir = File.dirname(str) # "/home/dave"
file1 = File.basename(str) # "podbay.rb"
file2 = File.basename(str,".rb") # "podbay"
Хотя это методы класса
File
, на самом деле они просто манипулируют строками.
Упомянем также метод
File.split
, который возвращает обе компоненты (имя каталога и имя файла) в массиве из двух элементов:
info = File.split(str) # ["/home/dave","podbay.rb"]
Метод класса
expand_path
преобразует путевое имя в абсолютный путь. Если операционная система понимает сокращения
открытый файл, то он вернет путевое имя, по которому файл был открыт.
file = File.new("../../foobar")
name = file.path # "../../foobar"
Константа
File::Separator
равна символу, применяемому для разделения компонентов путевого имени (в Windows это обратная косая черта, а в UNIX — прямая косая черта). Имеется также синоним