Чтение онлайн

ЖАНРЫ

Программирование на языке Ruby
Шрифт:

Dir.chdir("/home/guy/sandbox/tmp")

Dir.chroot("/home/guy/sandbox")

puts Dir.pwd # "/tmp"

10.1.30. Обход каталога

Метод класса

foreach
— это итератор, который последовательно передает в блок каждый элемент каталога. Точно так же ведет себя метод экземпляра
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 такую операцию выполняет метод

FileUtils.makedirs
(из библиотеки
fileutils
):

require "fileutils"

FileUtils.makedirs("/tmp/these/dirs/need/not/exist")

10.1.33. Рекурсивное удаление каталога

В UNIX команда

rm -rf dir
удаляет все поддерево начиная с каталога
dir
. Понятно, что применять ее надо с осторожностью.

В последних версиях Ruby в класс

Pathname
добавлен метод
rmtree
, решающий ту же задачу. В модуле
FileUtils
есть аналогичный метода
rm_r
.

require 'pathname'

dir = Pathname.new("/home/poole/")

dir.rmtree

# или:

require 'fileutils'

FileUtils.rm_r("/home/poole")

10.1.34. Поиск файлов и каталогов

Ниже мы воспользовались стандартной библиотекой

find.rb
для написания метода, который находит один или более файлов и возвращает их список в виде массива. Первый параметр — это начальный каталог, второй — либо имя файла (строка), либо регулярное выражение.

require "find"

def findfiles(dir, name)

 list = []

 Find.find(dir) do |path|

Find.prune if [".",".."].include? Path

case name

when String

list << path if File.basename(path) == name

when Regexp

list << path if File.basename(path) =~ name

else

raise ArgumentError

end

 end

 list

end

findfiles "/home/hal", "toc.txt"

# ["/home/hal/docs/toc.txt", "/home/hal/misc/toc.txt"]

findfiles "/home", /^[a-z]+.doc/

# ["/home/hal/docs/alpha.doc", "/home/guy/guide.doc",

# "/home/bill/help/readme.doc"]

10.2.

Доступ к данным более высокого уровня

Часто возникает необходимость хранить и извлекать данные более прозрачным способом. Модуль

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.

Поделиться с друзьями: