Ruby File I/O


Открытие потоков

Перед осуществлением ввода или вывода должен существовать IO-объект, из которого будут считываться или в который будут записываться данные. В классе IO определяются фабричные методы new, open, рореп и piре, но это низкоуровневые методы, чья работа зависит от применяемой операционной системы, далее рассматриваются наиболее распространенные способы получения IO-объектов.

Объект ввода-вывода (IO-объект) — это поток данных: источник байтов или символов, из которого можно производить считывание, или приемник байтов или символов, в который можно производить запись. Класс File является подклассом класса IO. IO-объекты также представляют потоки «стандартного входа» и «стандартного выхода», используемые для чтения из и записи в консольное устройство. Модуль stringio, принадлежащий стандартной библиотеке, позволяет создавать потоковые оболочки вокруг строковых объектов. И наконец, сокет-объекты, используемые при работе с сетями, также являются IО-объектами.

Режим Описание

" г " Открытие для чтения. Этот режим используется по умолчанию

"г+ " Открытие для чтения и записи с начала файла. Выдает сбой, если файл не существует

"w" Открытие для записи. Создает новый или усекает существующий файл

"w+" То же, что и "w", но допускается также и чтение файла

"а" Открытие для записи, но с добавлением в конец файла, если он уже существует

"а+" То же, что и "а", но допускается также и чтение файла

Ruby предоставляет целый набор I/O методов, реализованных в модуле ядра. Все методы ввода-вывода являются производными от класса IO. Класс IO предоставляет все основные методы, такие как: read, write, gets, puts, readline, getc, and printf.

The puts Statement

Оператор puts указывает программе отобразить значение, хранящееся в переменной. Это добавит новую строку в конец каждой записываемой строки.

Пример:

#!/usr/bin/ruby

val1 = "This is variable one"

val2 = "This is variable two"

puts val1

puts val2

Это даст такой результат:

This is variable one

This is variable two

The gets Statement

Оператор gets может использоваться для получения данных со стандартного потока ввода STDIN (в нашем случае это клавиатура).

Пример:

В следующем коде показано, как использовать оператор gets. Этот код предложит пользователю ввести значение, которое будет сохранено в переменной val и в итоге будет напечатано в STDOUT (в нашем случае это экран).

#!/usr/bin/ruby

puts "Enter a value :"

val = gets

puts val

Получится что то типа этого:

Enter a value :

ruby stdout

ruby stdout

The putc Statement

В отличие от оператора puts, который выводит всю строку на экран, оператор putc может использоваться для вывода одного символа за раз.

Пример:

#!/usr/bin/ruby

str = "Hello Ruby!"

putc str

И в итоге:

H

The print Statement

Оператор print это почти оператор puts, с одним не мало важным отличием, которое состоит в том, что оператор puts переходит на следующую строку после печати содержимого, тогда как с оператором print курсор располагается на той же строке.

Пример:

#!/usr/bin/ruby

print "Hello World"

puts "Good Morning"

Что выведет на экран следующее:

Hello WorldGood Morning

Открытие и закрытие файлов

До сих пор мы эксперементировали с стандартным вводом и выводом. Теперь посмотрим, как работать с реальными файлами данных.

Метод File.new

Вы можете создать объект File, используя метод File.new для чтения или записи, или того и другого, в зависимости от режима строки. Наконец, вы можете использовать метод File.close, чтобы закрыть этот файл.

Синтакс:

aFile = File.new("filename", "mode")

# ... process the file

aFile.clos

Метод File.open

Вы можете использовать метод File.open для создания нового файлового объекта и присвоения этого файлового объекта файлу. Однако между методами File.open и File.new есть одно различие. Разница в том, что метод File.open может быть связан с блоком, тогда как вы не можете сделать то же самое, используя метод File.new.

Как и в других языках, например Python работа с файлами осуществляется через специальный абстрактный файловый объект. В зависимости от способа создания такого объекта, он может быть привязан как к физическому файлу на диске, так и другому устройству, поддерживающему схожие операции (стандартный ввод/вывод и пр.).


File.open("filename", "mode") do |aFile|

# ... process the file

end

Чтение и запись файлов

Те же методы, которые мы использовали для «простого» ввода-вывода, доступны для всех файловых объектов. Итак, get читает строку из стандартного ввода, а aFile.gets читает строку из файлового объекта aFile.

Однако объекты ввода-вывода предоставляют дополнительный набор методов доступа, облегчающих нашу жизнь.

Метод sysread

Вы можете использовать метод sysread для чтения содержимого файла. Вы можете открыть файл в любом из режимов при использовании метода sysread.

Например:

Создадим текстовой файл, длиной 30 символов:

$ cat > input.txt

The sysread Method for example

^C

И собственно код Ruby, демонстрирующий метод sysread:

#!/usr/bin/ruby

aFile = File.new("input.txt", "r")

if aFile

content = aFile.sysread(23)

puts content

else

puts "Unable to open file!"

end

В итоге:

The sysread Method for

Оператор sysread выведет первые 23 символа файла, как и задано. Указатель файла теперь будет помещен на 24-й символ в файле.

Метод syswrite

Вы можете использовать метод syswrite для записи содержимого в файл.

Например, создадим пустой файл

> input_1.txt

И собственно код Ruby, демонстрирующий метод syswrite:

#!/usr/bin/ruby

aFile = File.new("input_1.txt", "r+")

if aFile

aFile.syswrite("ABCDEF")

else

puts "Unable to open file!"

end

И в итоге:

vim input_1.txt

ABCDEF

Метод each_byte

Этот метод принадлежит к классу File. Метод each_byte всегда связан с блоком. Рассмотрим следующий пример кода:

Создадим файл:

cat > input_2.txt

testing purpose: each_byte Method

^C

Создадим код Ruby:

#!/usr/bin/ruby

aFile = File.new("input_2.txt")

if aFile

aFile.each_byte {|ch| putc ch; putc ?. }

else

puts "Unable to open file!"

end

Результат:

t.e.s.t.i.n.g. .p.u.r.p.o.s.e.:. .e.a.c.h._.b.y.t.e. .M.e.t.h.o.d.

Символы передаются один за другим в переменную ch и затем отображаются на экране

Метод IO.readlines

Класс File является подклассом класса IO. Класс IO также имеет несколько методов, которые можно использовать для управления файлами. Один из методов класса IO - IO.readlines. Этот метод по очереди возвращает содержимое файла. В следующем коде показано использование метода IO.readlines:

Создадим файл;

cat > input_3.txt

0. testing purpose: each_byte Method

1. testing purpose: IO.readlines Method

2. testing purpose: IO.foreach Method

^C

Напишем код:

#!/usr/bin/ruby

arr = IO.readlines("input_3.txt")

puts arr[0]

puts arr[1]

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

0. testing purpose: each_byte Method

1. testing purpose: IO.readlines Method

Метод IO.foreach

Этот метод также возвращает вывод построчно. Разница между методом IO.foreach и методом IO.readlines заключается в том, что метод IO.foreach связан с блоком. Однако, в отличие от метода IO.readlines, метод foreach не возвращает массив. Например:

#!/usr/bin/ruby

IO.foreach("input_3.txt"){|block| puts block}

Этот код будет передавать содержимое файла построчно в блок переменных, а затем вывод будет отображаться на экране.

Результат:

0. testing purpose: each_byte Method

1. testing purpose: IO.readlines Method

2. testing purpose: IO.foreach Method

Переименование и удаление файлов

Вы можете переименовывать и удалять файлы программно с помощью Ruby с посредством методов переименования и удаления.4

Ниже приведен пример переименования существующего файла input.txt.:

#!/usr/bin/ruby

# Rename a file from input.txt to input_4.txt

File.rename( "input.txt", "input_4.txt" )

Далее пример удаления input_4.txt:

#!/usr/bin/ruby

# Delete file input_4.txt

File.delete("input_4.txt")

File Modes and Ownership

Используйте метод chmod с маской, чтобы изменить permissions/access list для файла

Ниже приведен пример изменения режима существующего файла test.txt на значение маски.

#!/usr/bin/ruby

file = File.new( "test.txt", "w" )

file.chmod( 0755 )

File Inquiries

Следующая команда проверяет, существует ли файл перед его открытием

#!/usr/bin/ruby

File.open("file.rb") if File::exists?( "file.rb" )

Следующая команда запрашивает, действительно ли файл является файлом

#!/usr/bin/ruby

# This returns either true or false

File.file?( "text.txt" )

Следующая команда выясняет, является ли данное имя файла каталогом

#!/usr/bin/ruby

# a directory

File::directory?( "/usr/local/bin" ) # => true

# a file

File::directory?( "file.rb" ) # => false

Следующая команда определяет, доступен ли файл для чтения, записи или выполнения

#!/usr/bin/ruby

File.readable?( "test.txt" ) # => true

File.writable?( "test.txt" ) # => true

File.executable?( "test.txt" ) # => false

Следующая команда определяет, имеет ли файл нулевой размер или нет

#!/usr/bin/ruby

File.zero?( "test.txt" ) # => true

Следующая команда возвращает размер файла

#!/usr/bin/ruby

File.size?( "text.txt" ) # => 1002

Следующая команда может использоваться для определения типа файла

#!/usr/bin/ruby

File::ftype( "test.txt" ) # => file

Метод ftype определяет тип файла, возвращая один из следующихfile, directory, characterSpecial, blockSpecial, fifo, link, socket, or unknown.

Следующая команда может использоваться, чтобы узнать, когда файл был создан, изменен или последний раз был осуществлен доступ к нему:

$ irb

irb(main):001:0> File::ctime( "ruby_9.rb" ) #=> 2020-08-26 12:20:50.672461621 +0300

irb(main):002:0> File::mtime( "ruby_9.rb" ) #=> 2020-08-26 12:20:50.636461623 +0300

irb(main):003:0> File::atime( "ruby_9.rb" ) #=> 2020-08-26 12:21:01.628461061 +0300

irb(main):004:0> File::ftype( "ruby_9.rb" ) #=> "file"

irb(main):005:0> File.size?( "ruby_9.rb" ) #=> 958

irb(main):004:0>

Directories in Ruby

Все файлы содержатся в разных каталогах, и Ruby без проблем справляется с ними. В то время как класс File обрабатывает файлы, каталоги обрабатываются классом Dir.

Navigating Through Directories

Чтобы сменить каталог в программе Ruby, используйте Dir.chdir следующим образом. В этом примере текущий каталог изменяется на /usr/bin

Dir.chdir("/usr/bin")

Вы можете узнать текущий каталог с помощью Dir.pwd

puts Dir.pwd # This will return something like /usr/bin

Вы можете получить список файлов и каталогов в определенном каталоге, используя Dir.entries

puts Dir.entries("/usr/bin").join(' ')

Dir.entries возвращает массив со всеми записями в указанном каталоге. Dir.foreach предоставляет ту же функцию

Dir.foreach("/usr/bin") do |entry|

puts entry

end

Еще более краткий способ получения списков каталогов - использовать метод массива классов Dir

$ irb

irb(main):001:0> Dir["/home/dell/*"]

=> ["/home/dell/ruby_29.rb", "/home/dell/ruby_14.rb", "/home/dell/ruby_32.rb", "/home/dell/ruby_36.rb", "/home/dell/Telegram", "/home/dell/ruby_11.rb", "/home/dell/ruby_20.rb", "/home/dell/ruby_8.rb", "/home/dell/xsudoky-1.0.7.tar.gz", "/home/dell/fgf", "/home/dell/vmware", "/home/dell/Изображения", "/home/dell/Рабочий стол", "/home/dell/ruby_7.rb", "/home/dell/ruby_24.rb", "/home/dell/\\", "/home/dell/Загрузки", "/home/dell/ruby_25.rb", "/home/dell/ruby_34.rb", "/home/dell/xcv.rb", "/home/dell/ruby_3.rb", "/home/dell/input_1.txt", "/home/dell/Шаблоны", "/home/dell/ruby_18.rb", "/home/dell/ruby_4.rb", "/home/dell/Музыка", "/home/dell/ruby_21.rb", "/home/dell/input_4.txt", "/home/dell/ruby_23.rb", "/home/dell/ruby_2.rb", "/home/dell/Документы", "/home/dell/ruby_26.rb", "/home/dell/lxc-rest", "/home/dell/ruby_1.rb", "/home/dell/ruby_22.rb", "/home/dell/ruby_10.rb", "/home/dell/xsudoky-1.0.7", "/home/dell/ruby_13.rb", "/home/dell/Видео", "/home/dell/ruby_5.rb"]

irb(main):002:0>


Creating a Directory

Dir.mkdir можно использовать для создания каталогов

Dir.mkdir("mynewdir")

Вы также можете установить разрешения для нового каталога (а не того, который уже существует) с помощью mkdir

NOTE − The mask 755 sets permissions owner, group, world [anyone] to rwxr-xr-x where r = read, w = write, and x = execute.

Dir.mkdir( "mynewdir", 755 )

Deleting a Directory

Dir.delete можно использовать для удаления каталога. Dir.unlink и Dir.rmdir выполняют ту же функцию и предоставляются для удобства.

Dir.delete("testdir")

Creating Files & Temporary Directories

Временные файлы - это файлы, которые могут быть созданы на короткое время во время выполнения программы, но не являются постоянным хранилищем информации. Dir.tmpdir предоставляет путь к временному каталогу в текущей системе, хотя этот метод по умолчанию недоступен. Чтобы сделать Dir.tmpdir доступным, необходимо использовать require 'tmpdir'.

Вы можете использовать Dir.tmpdir с File.join для создания независимого от платформы временного файла -

tempfilename = File.join(Dir.tmpdir, "tingtong")

tempfile = File.new(tempfilename, "w")

tempfile.puts "This is a temporary file"

tempfile.close

File.delete(tempfilename)

Этот код создает временный файл, записывает в него данные и удаляет его. Стандартная библиотека Ruby также включает библиотеку под названием Tempfile, которая может создавать для вас временные файлы -

require 'tempfile'

f = Tempfile.new('tingtong')

f.puts "Hello"

puts f.path

f.close

Built-in Functions

Вот встроенные функции Ruby для обработки файлов и каталогов