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

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

Давайте предположим, что в нашей файловой системе есть файл example.txt, который содержит следующее:

- Привет! Ты из Китая, верно?
– Да, верно. Привет.
- Я слышал, что Китай был первой страной, которая приняла идеи коммунизма.
- Да, это правда. Мы пытаемся построить социалистическое общество с китайской спецификой.
- А что вы думаете об идеологии коммунизма?
- Я думаю, что коммунизм может быть хорошим идеалом, если будет правильно реализован. Он должен быть основан на равном распределении ресурсов и справедливости для всех людей.
- А что вы думаете о перестройке в России и распаде Советского Союза?
- Я думаю, что это был сложный период в истории России и СССР. Я уважаю решение народа России о переходе к рыночной экономике и демократии. Но я также считаю, что коммунизм может быть реализован лишь в том случае, если есть поддержка и понимание со стороны жителей страны.

Первое, что необходимо сделать для того, чтобы прочитать содержимое, это открыть файл. Открытие файла принимает 2 аргумента: путь до файла и права на этот файл

# В данном случае мы открываем наш файл по пути '/some/path/example.txt' с правами на чтение
# результатом открытия файла будет обхект класса File содержащий значение файла, а также метаинформацию
file = File.open("/some/path/example.txt", "r")

Можно выделить 3 основных права на файл:

  1. r - read/чтение

  2. a - append/добавление (мы можем добавить в файл значение, но не можем изменить уже существующее)

  3. w - write/запись

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

После того как мы открыли файл нам доступны следующие методы:

  • read - перенос значения в строкове представление. При этом наши переносы строки, пробелы, табуляции сохраняются

  • readlines - перенос значения в массив строк, где каждая новая строка будет новым значением в массиве

  • each_line - возвращает объект Enumerator. Если открыть в нем блок кода, то можно проитерировать каждую строчку файла

  • readline - читает строку в файле и при следующем вызове этого же метода будет прочитана следующая строка

  • seek - перевод курсора к указанной позиции в файле. Принимает первым аргументом размер отступа, а вторым от чего именно будет отступ:

    • :END - с конца

    • :SET - с начала

    • :CUR - от текущей позиции

  • size - размер файла в байтах

  • birthtime - дата создания объекта

  • atime - дата последнего доступа к файлу

Важно понимать отличие между readlines и each_line с readline. reeadlines читает содержимое файла целиком и целиком помещает его в массив. Это может быть эффективно при работе с небольшими файлами, но если файл весит 1 ГБ, то весь 1ГБ будет помещен в память компьютера, а как мы знаем размеры памяти куда более ограничены по сравнению с постоянной памятью по типу SSD или HHD. each_line и readline отличается своей возможностью лениво читать файл. Если текущая итерация обрабатвает 1 строчку файла, то остальные строчки не будут помещены в память. Когда итерация начнет обрабатывать 2 строчку, то данные из первой строки очистятся из памяти, а данные из 3 и последующей не будут в нее загружены.

После завершения работы нам необходимо всегда закрывать работу файла вызвав у него метод close. Кроме того, мы можем не вызывать этот метод, если будет работать с файлом внутри блока при открытии, т.к. закрытие файла будет вызвано автоматически по окончанию работы блока кода:

Изменение файлов

Давайте сразу на примере посмотрим как мы можем записывать в файл:

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

Такой же результат мы получим, если откроем файл с правами a

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

  • File.rename - переименновать файл

  • File.size - получить размер файла в байтах

  • File.exists? - существует ли файл

  • File.directory? - является ли файл директорией

  • File.file? - является ли файл файлом

  • File.foreach - такой же функционал как и у метода объекта .each_line

  • File.read - такой же функционал как и у метода объекта .read

  • File.readlines - такой же функционал как и у метода объекта .readlines

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

Работа с директорией

С файлами мы разобрались, но что делать, когда мы хотим работать сразу с несколькими файлами, объеденных в одной директории ? Для этого у нас есть класс Dir со своимсобственным функционалом. Вот несколько наиболее полезных классовых методов у него:

  • Dir.mkdir - создание новой директории. Внимание этот метод не создает вложнные каталоги. Если мы попытаемся создат ькаталог в несуществующем каталоге, то получим ошибку.

  • Dir.entries - возвращает массив названий файлов и каталогов в указаной директории. Учтите6 что это именно массив названий файлов, а не объектов File.

  • Dir.glob - Возвращает список файлов и директорий по паттерн матчингу. * обозначает любое количество символов, включая ноль символов. ** обозначает любое количество символов, включая вложенные каталоги. Кроме символа * также используются символы ? (заменяет один любой символ) и [] (определяет диапазон возможных символов). Например:

    • *.txt - соответствует всем файлам с расширением .txt в текущей директории.

    • docs/*.txt - соответствует всем файлам с расширением .txt в папке docs, находящейся в текущей директории.

    • **/*.txt - соответствует всем файлам с расширением .txt в любой вложенной директории, начиная с текущей.

Давайте посмотрим на пример использования:

Задание file_tree

Напишите метод file_hierachy(path) принимающий путь до директории. Выведите в консоль файлы в древовидной форме. Как это должно выглядеть в консоли:

Задание folder_size

Напишите метод calculate_folder_size(path), который принимает путь до директории и возвращает размер папки в гигабайтах, округленный до 2 символов после запятой

Рекоммендации:

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

Last updated