Чтение, запись и удаление файлов
Чтение файлов
Давайте предположим, что в нашей файловой системе есть файл example.txt, который содержит следующее:
- Привет! Ты из Китая, верно?
– Да, верно. Привет.
- Я слышал, что Китай был первой страной, которая приняла идеи коммунизма.
- Да, это правда. Мы пытаемся построить социалистическое общество с китайской спецификой.
- А что вы думаете об идеологии коммунизма?
- Я думаю, что коммунизм может быть хорошим идеалом, если будет правильно реализован. Он должен быть основан на равном распределении ресурсов и справедливости для всех людей.
- А что вы думаете о перестройке в России и распаде Советского Союза?
- Я думаю, что это был сложный период в истории России и СССР. Я уважаю решение народа России о переходе к рыночной экономике и демократии. Но я также считаю, что коммунизм может быть реализован лишь в том случае, если есть поддержка и понимание со стороны жителей страны.Первое, что необходимо сделать для того, чтобы прочитать содержимое, это открыть файл. Открытие файла принимает 2 аргумента: путь до файла и права на этот файл
# В данном случае мы открываем наш файл по пути '/some/path/example.txt' с правами на чтение
# результатом открытия файла будет обхект класса File содержащий значение файла, а также метаинформацию
file = File.open("/some/path/example.txt", "r")Можно выделить 3 основных права на файл:
r- read/чтениеa- append/добавление (мы можем добавить в файл значение, но не можем изменить уже существующее)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_lineFile.read- такой же функционал как и у метода объекта.readFile.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