Хэл Фултон - Программирование на языке Ruby
- Название:Программирование на языке Ruby
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2007
- Город:Москва
- ISBN:5-94074-357-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Хэл Фултон - Программирование на языке Ruby краткое содержание
Ruby — относительно новый объектно-ориентированный язык, разработанный Юкихиро Мацумото в 1995 году и позаимствовавший некоторые особенности у языков LISP, Smalltalk, Perl, CLU и других. Язык активно развивается и применяется в самых разных областях: от системного администрирования до разработки сложных динамических сайтов.
Книга является полноценным руководством по Ruby — ее можно использовать и как учебник, и как справочник, и как сборник ответов на вопросы типа «как сделать то или иное в Ruby». В ней приведено свыше 400 примеров, разбитых по различным аспектам программирования, и к которым автор дает обстоятельные комментарии.
Издание предназначено для программистов самого широкого круга и самой разной квалификации, желающих научиться качественно и профессионально работать на Ruby.
Программирование на языке Ruby - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
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
(то есть считывает весь файл в память).
Откуда мы получаем ввод? Есть переменная $stdin
, которая по умолчанию равна STDIN
. Точно так же существует поток стандартного вывода для ошибок ( $stderr
, по умолчанию равен STDERR
).
Еще имеется интересный глобальный объект ARGF
, представляющий конкатенацию всех файлов, указанных в командной строке. Это не объект класса File
, хотя и напоминает таковой. По умолчанию ввод связан именно с этим объектом, если в командной строке задан хотя бы один файл.
# Прочитать все файлы, а затем вывести их.
puts ARGF.read
# А при таком способе более экономно расходуется память:
while ! ARGF.eof?
puts ARGF.readline
end
# Пример: ruby cat.rb file1 file2 file3
При чтении из стандартного ввода ( stdin
) методы Kernel
не вызываются. Потому можно обойти (или не обходить) ARGF
, как показано ниже:
# Прочитать строку из стандартного ввода.
str1 = STDIN.gets
# Прочитать строку из ARGF.
str2 = ARGF.gets
# А теперь снова из стандартного ввода.
str3 = STDIN.gets
10.1.8. Буферизованный и небуферизованный ввод/вывод
В некоторых случаях Ruby осуществляет буферизацию самостоятельно. Рассмотрим следующий фрагмент:
print "Привет... "
sleep 10
print "Пока!\n"
Если запустить эту программу, то вы увидите, что сообщения «Привет» и «Пока» появляются одновременно, после завершения sleep
. При этом первое сообщение не завершается символом новой строки.
Это можно исправить, вызвав метод flush
для опустошения буфера вывода. В данном случае вывод идет в поток $defout
(подразумеваемый по умолчанию для всех методов Kernel
, которые занимаются выводом). И поведение оказывается ожидаемым, то есть первое сообщение появляется раньше второго.
print "Привет... "
STDOUT.flush
sleep 10
print "Пока!\n"
Буферизацию можно отключить (или включить) методом sync=
, а метод sync
позволяет узнать текущее состояние.
buf_flag = $defout.sync # true
STDOUT.sync = false
buf_flag = STDOUT.sync # false
Есть еще по крайней мере один низкий уровень буферизации, который не виден. Если метод getc
возвращает символ и продвигает вперед указатель файла или потока, то метод ungetc
возвращает символ назад в поток.
ch = mystream.getc # ?А
mystream.ungetc(?C)
ch = mystream.getc # ?C
Тут следует иметь в виду три вещи. Во-первых, только что упомянутая буферизация не имеет отношения к механизму буферизации, о котором мы говорили выше в этом разделе. Иными словами, предложение sync=false
не отключает ее. Во-вторых, вернуть в поток можно только один символ; при попытке вызвать метод ungetc
несколько раз будет возвращен только символ, прочитанный последним. И, в-третьих, метод ungetc
не работает для принципиально небуферизуемых операций (например, sysread
).
10.1.9. Манипулирование правами владения и разрешениями на доступ к файлу
Вопрос о владении файлами и разрешениях сильно зависит от платформы. Как правило, в системе UNIX функций больше, чем предоставляет Ruby, а на других платформах многие возможности не реализованы.
Читать дальшеИнтервал:
Закладка: