— это итератор, который последовательно передает в блок каждый элемент каталога. Точно так же ведет себя метод экземпляра
each
.
Dir.foreach("/tmp") { |entry| puts entry }
dir = Dir.new("/tmp")
dir.each { |entry| puts entry }
Оба
фрагмента печатают одно и то же (имена всех файлов и подкаталогов в каталоге /tmp).
10.1.31. Получение содержимого каталога
Метод класса
Dir.entries
возвращает массив, содержащий все элементы указанного каталога:
list = Dir.entries("/tmp") # %w[. .. alpha.txt beta.doc]
Как видите, включаются и элементы, соответствующие текущему и родительскому каталогу. Если они вам не нужны, придется отфильтровать их вручную.
10.1.32. Создание цепочки каталогов
Иногда необходимо создать глубоко вложенный каталог, причем промежуточные каталоги могут и не существовать. В UNIX мы воспользовались бы для этого командой
mkdir -p
.
В программе на Ruby такую операцию выполняет метод
для написания метода, который находит один или более файлов и возвращает их список в виде массива. Первый параметр — это начальный каталог, второй — либо имя файла (строка), либо регулярное выражение.
Часто возникает необходимость хранить и извлекать данные более прозрачным способом. Модуль
Marshal
предоставляет простые средства сохранения объектов а на его основе построена библиотека
PStore
. Наконец, библиотека
dbm
позволяет организовать нечто вроде хэша на диске. Строго говоря, она не относится к теме данного раздела, но уж слишком проста, чтобы рассказывать о ней в разделе, посвященном базам данных.
10.2.1. Простой маршалинг
Часто бывает необходимо создать объект и сохранить его для последующего использования. В Ruby есть рудиментарная поддержка для обеспечения устойчивости объекта или маршалинга. Модуль
Marshal
позволяет сериализовать и десериализовать объекты.
# Массив элементов [composer, work, minutes]
works = [["Leonard Bernstein","Overture to Candide",11],
["Aaron Copland","Symphony No. 3",45],
["Jean Sibelius","Finlandia",20]]
# Мы хотим сохранить его для последующего использования...
File.open("store","w") do |file|
Marshal.dump(works,file)
end
# Намного позже...
File.open("store") do |file|
works = Marshal.load(file)
end
Недостаток такого подхода заключается в том, что не все объекты можно сохранить. Для объектов, включающих другие объекты низкого уровня, маршалинг невозможен. К числу таких низкоуровневых объектов относятся, в частности,
IO
,
Proc
и
Binding
. Нельзя также сериализовать синглетные объекты, анонимные классы и модули.
Метод
Marshal.dump
можно вызывать еще двумя способами. Если он вызывается с одним параметром, то возвращает данные в виде строки, в которой первые два байта — это номер старшей и младшей версии.
s = Marshal.dump(works)
p s[0] # 4
p s[1] # 8
Обычно попытка загрузить такие данные оказывается успешной только в случае, если номера старших версий совпадают и номер младшей версии данных не больше младшей версии метода. Но если при вызове интерпретатора Ruby задан флаг «болтливости» (
verbose
или
v
), то версии должны совпадать точно. Эти номера версий не связаны с номерами версий Ruby.