с = ios.getc
puts 'с = #{c}' # с = 105
ios.ungetc(?w)
puts ios.string.dump # 'abcdexyzwjkl
ABC
123'
puts 'Ptr = #{ios.tell}'
s1 = ios.gets # 'wjkl'
s2 = ios.gets # 'ABC'
10.1.25. Чтение данных, встроенных в текст программы
Когда подростком вы учили язык BASIC, копируя программы из журналов, то, наверное, для удобства часто пользовались предложением DATA
. Оно позволяло включать информацию прямо в текст программы, но читать ее так, будто она поступает из внешнего источника.
При желании то же самое можно сделать и в Ruby. Директива __END__
в конце программы говорит, что дальше идут встроенные данные. Их можно читать из глобальной константы DATA
, которая представляет собой обычный объект IO
. (Отметим, что маркер __END__
должен располагаться с начала строки.)
# Распечатать все строки 'задом наперед'...
DATA.each_line do |line|
puts line.reverse
end
__END__
A man, a plan, a canal... Panama!
Madam, I'm Adam.
,siht daer nac uoy fI
.drah oot gnikrow neeb ev'uoy
10.1.26. Чтение исходного текста программы
Если вы хотите получить доступ к исходному тексту собственной программы, то можете воспользоваться уже описанным выше трюком (см. раздел 10.1.25).
Глобальная константа DATA
— это объект класса IO
, ссылающийся на данные, которые расположены после директивы __END__
. Но если выполнить метод rewind
, то указатель файла будет переустановлен на начало текста программы.
Следующая программа выводит собственный текст, снабжая его номерами строк. Это не очень полезно, но, быть может, вы найдете и другие применения такой техники.
DATA.rewind
num = 1
DATA.each_line do |line|
puts '#{'%03d' % num} #{line}'
num += 1
end
__END__
Отметим, что наличие директивы __END__
обязательно — без нее к константе DATA
вообще нельзя обратиться.
10.1.27. Работа с временными файлами
Во многих случаях необходимо работать с файлами, которые по сути своей анонимны. Мы не хотим возиться с присваиванием им имен и проверять, что при этом не возникает конфликтов с существующими файлами. И помнить о том, что такие файлы нужно удалять, тоже не хочется.
Все эти проблемы решает библиотека Tempfile
. Метод new
(синоним open
) принимает базовое имя в качестве строки-затравки и конкатенирует его с идентификатором процесса и уникальным порядковым номером. Необязательный второй параметр — имя каталога, в котором создается временный файл; по умолчанию оно равно значению первой из существующих переменных окружения tmpdir
, tmp
или temp
, а если ни одна из них не задана, то '/tmp'
.
Возвращаемый объект IO
можно многократно открывать и закрывать на протяжении всей работы программы, а по ее завершении временный файл будет автоматически удален.
У метода close
есть необязательный флаг; если он равен true
, то файл удаляется сразу после закрытия (не дожидаясь завершения программы). Метод path
возвращает полное имя файла, если оно вам по какой-то причине понадобится.
require 'tempfile'
temp = Tempfile.new('stuff')
name = temp.path # '/tmp/stuff17060.0'
temp.puts 'Здесь был Вася'
temp.close
# Позже...
temp.open
str = temp.gets # 'Здесь был Вася'
temp.close(true) # Удалить СЕЙЧАС.
10.1.28. Получение и изменение текущего каталога
Получить имя текущего каталога можно с помощью метода Dir.pwd
(синоним Dir.getwd
). Эти имена уже давно употребляются как сокращения от «print working directory» (печатать рабочий каталог) и «get working directory» (получить рабочий каталог). На платформе Windows символы обратной косой черты преобразуются в символы прямой косой черты.
Для изменения текущего каталога служит метод Dir.chdir
. В Windows в начале строки можно указывать букву диска.
Dir.chdir('/var/tmp')
puts Dir.pwd # '/var/tmp'
puts Dir.getwd # '/var/tmp'
Этот метод также принимает блок в качестве параметра. Если блок задан, то текущий каталог изменяется только на время выполнения блока, а потом восстанавливается первоначальное значение: