line = file.readline # "Строка 1.\n"
puts "#{line.size} символов." # 10 символов,
file.close
file = File.open("data","rb")
line = file.readline # "Строка 1.\r\n"
puts "#{line.size} символов." # 11 символов.
file.close
Отметим, что упомянутый в коде метод binmodeпереключает поток в двоичный режим. После переключения вернуться в текстовый режим невозможно.
file = File.open("data")
file.binmode
line = file.readline # "Строка 1.\r\n"
puts {line.size} символов." # 11 символов.
file.close
При необходимости выполнить низкоуровневый ввод/вывод можете воспользоваться методами sysreadи syswrite. Первый принимает в качестве параметра число подлежащих чтению байтов, второй принимает строку и возвращает число записанных байтов. (Если вы начали читать из потока методом sysread, то никакие другие методы использовать не следует. Результаты могут быть непредсказуемы.)
input = File.new("infile")
output = File.new("outfile")
instr = input.sysread(10);
bytes = output.syswrite("Это тест.")
Отметим, что метод sysreadвозбуждает исключение EOFErrorпри попытке вызвать его, когда достигнут конец файла (но не в том случае, когда конец файла встретился в ходе успешной операции чтения). Оба метода возбуждают исключение SystemCallErrorпри возникновении ошибки ввода/вывода.
При работе с двоичными данными могут оказаться полезны метод packиз класса Arrayи метод unpackиз класса String.
10.1.6. Блокировка файлов
В тех операционных системах, которые поддерживают такую возможность, метод flockкласса Fileблокирует или разблокирует файл. Вторым параметром может быть одна из констант File::LOCK_EX, File::LOCK_NB, File::LOCK_SH, File::LOCK_UNили их объединение с помощью оператора ИЛИ. Понятно, что многие комбинации не имеют смысла; чаще всего употребляется флаг, задающий неблокирующий режим.
file = File.new("somefile")
file.flock(File::LOCK_EX) # Исключительная блокировка; никакой другой
# процесс не может обратиться к файлу.
file.flock(File::LOCK_UN) # Разблокировать.
file.flock(File::LOCK_SH) # Разделяемая блокировка (другие
# процессы могут сделать то же самое).
file.flock(File::LOCK_UN) # Разблокировать.
locked = file.flock(File::LOCK_EX | File::LOCK_NB)
# Пытаемся заблокировать файл, но не приостанавливаем программу, если
# не получилось; в таком случае переменная locked будет равна false.
Для семейства операционных систем Windows эта функция не реализована.
10.1.7. Простой ввод/вывод
Вы уже знакомы с некоторыми методами ввода/вывода из модуля Kernel; мы вызывали их без указания вызывающего объекта. К ним относятся функции getsи puts, а также print, printfи p(последний вызывает метод объекта inspect, чтобы распечатать его в понятном для нас виде).
Но есть и другие методы, которые следует упомянуть для полноты. Метод putcвыводит один символ. (Парный метод getcне реализован в модуле Kernelпо техническим причинам, однако он есть у любого объекта класса IO). Если параметром является объект String, то печатается первый символ строки.
putc(?\n) # Вывести символ новой строки.
putc("X") # Вывести букву X.
Интересный вопрос: куда направляется вывод, если эти методы вызываются без указания объекта? Начнем с того, что в среде исполнения Ruby определены три глобальные константы, соответствующие трем стандартным потокам ввода/вывода, к которым мы привыкли в UNIX. Это STDIN, STDOUTи STDERR. Все они имеют тип IO.
Имеется также глобальная переменная $stdout, именно в нее направляется весь вывод, формируемый методами из Kernel. Она инициализирована значением STDOUT, так что данные отправляются на стандартный вывод, как и следовало ожидать. В любой момент переменной $stdoutможно присвоить другое значение, являющееся объектом IO.
diskfile = File.new("foofile","w")
puts "Привет..." # Выводится на stdout.
$stdout = diskfile
puts "Пока!" # Выводится в файл "foofile".
diskfile.close
$stdout = STDOUT # Восстановление исходного значения.
puts "Это все." # Выводится на stdout.
Помимо метода getsв модуле Kernelесть методы ввода readlineи readlines. Первый аналогичен getsв том смысле, что возбуждает исключение EOFErrorпри попытке читать за концом файла, а не просто возвращает nil. Последний эквивалентен методу IO.readlines(то есть считывает весь файл в память).
Читать дальше
Конец ознакомительного отрывка
Купить книгу