Это старая версия документа!


Эксперимент 43. Файловая система. Файловые операции

Фа́йловая систе́ма (англ. file system) — порядок, определяющий способ организации, хранения и именования данных на носителях информации в компьютерах, а также в другом электронном оборудовании: цифровых фотоаппаратах, мобильных телефонах и т. п. Файловая система определяет формат содержимого и способ физического хранения информации, которую принято группировать в виде файлов. Конкретная файловая система определяет размер имен файлов (и каталогов), максимальный возможный размер файла и раздела, набор атрибутов файла.

Файловая система связывает носитель информации с одной стороны и интерфейс для доступа к файлам — с другой. Когда прикладная программа обращается к файлу, она не имеет никакого представления о том, каким образом расположена информация на носителе, так же как и о том, на каком физическом типе носителя (CD, жёстком диске, магнитной ленте, блоке флеш-памяти или другом) он записан. Всё, что знает программа — это имя файла, его размер и атрибуты. Эти данные она получает от файловой системы. Именно файловая система устанавливает, где и как будет записан файл на физическом носителе (например, жёстком диске).

Мы уже знаем, что микроконтроллер, на базе которого построен наш конструктор имеет Flash-память с организованной на ней файловой системой. Человек может получить доступ к этой «флешке», например, через файловый менеджер среды программирования EsPy. Но наши программы тоже могут работать с файловой системой. Мы уже загружали библиотеки и даже создавали файл с данными с температурных датчиков. Но это не все возможности. Давайте познакомимся с файловой системой поближе на примере следующей программы.

Программный код эксперимента

Exp43.ino
  1. #include "LittleFS.h"
  2.  
  3. void listDir(String path, bool showPath) {
  4. Serial.println();
  5. File dir = LittleFS.open(path, "r");
  6. File file = dir.openNextFile();
  7. while (dir) {
  8. Serial.print("name: ");
  9. if (showPath) Serial.print(file.fullName());
  10. else Serial.print(file.name());
  11.  
  12. if (file.isDirectory()) Serial.print(", type: folder, ");
  13. else Serial.print(" type: file, ");
  14.  
  15. Serial.print("size: ");
  16. Serial.println(file.size());
  17.  
  18. file = dir.openNextFile();
  19. }
  20. }
  21.  
  22. void setup() {
  23. Serial.begin(9600);
  24. Serial.println();
  25.  
  26. LittleFS.format();
  27. LittleFS.begin();
  28.  
  29. File file = LittleFS.open("/test.txt", "w");
  30. file.print("Some text");
  31. file.close();
  32. listDir("/", false);
  33.  
  34. LittleFS.mkdir("/dir");
  35. listDir("/", false);
  36.  
  37. file = LittleFS.open("/dir/test2.txt", "w");
  38. file.print("Some other text");
  39. file.close();
  40. listDir("/dir/", false);
  41. listDir("/dir/", true);
  42.  
  43. LittleFS.rename("/test.txt", "/test_new.txt");
  44. listDir("/", false);
  45.  
  46. LittleFS.remove("/test_new.txt");
  47. listDir("/", false);
  48. }
  49.  
  50. void loop() {
  51. }

Для работы с файловой системой необходимо подключить библиотеку:

  1. #include "LittleFS.h"

Для вывода содержимого директории мы написали специальную функцию:

  1. void listDir(String path, bool showPath) {
  2. Serial.println();
  3. File dir = LittleFS.open(path, "r");
  4. File file = dir.openNextFile();
  5. while (dir) {
  6. Serial.print("name: ");
  7. if (showPath) Serial.print(file.fullName());
  8. else Serial.print(file.name());
  9.  
  10. if (file.isDirectory()) Serial.print(", type: folder, ");
  11. else Serial.print(" type: file, ");
  12.  
  13. Serial.print("size: ");
  14. Serial.println(file.size());
  15.  
  16. file = dir.openNextFile();
  17. }
  18. }

Она принимает два аргумента: первый — путь к директории, содержимое которой нужно вывести, второй - определяет нужно ли при выводе названия файла указывать полный путь к нему.

Создаем объект директории:

  1. File dir = LittleFS.open(path, "r");

Открываем первый файл:

  1. File file = root.openNextFile();

Далее в цикле While сначала выводим в зависимости от аргумента showPath имя файла/директории с указанием пути или без:

  1. Serial.print("name: ");
  2. if (showPath) Serial.print(file.fullName());
  3. else Serial.print(file.name());

Определяем является ли объект директорией или файлом и печатаем соответствующий текст:

  1. if (file.isDirectory()) Serial.print(", type: folder, ");
  2. else Serial.print(" type: file, ");

Выводим размер объекта (для директории он всегда равен 0):

  1. Serial.print("size: ");
  2. Serial.println(file.size());

Открываем следующий файл в директории:

  1. file = dir.openNextFile();

После этого можно работать с функциями файловой системы. Для начала получим список файлов:

Exp43-1.py
  1. import os
  2.  
  3. files = os.listdir()
  4.  
  5. for file in files:
  6. print(file)

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

boot.py
init.mpy
lcd_api.py
esp8266_i2c_lcd.py
mfrc522.mpy
temp_data.csv

Мы видим список файлов. Однако нам может требоваться допонительная информация, например размер файлов. Для этого есть функция ilistdir()

Exp43-2.py
  1. import os
  2.  
  3. files = os.ilistdir()
  4. for file in files:
  5. print(file)

Программа выводит список файлов: Имя, тип (файл или директория), 0, размер файла в байтах

('boot.py', 32768, 0, 252)
('init.mpy', 32768, 0, 225)
('lcd_api.py', 32768, 0, 6882)
('esp8266_i2c_lcd.py', 32768, 0, 3293)
('mfrc522.mpy', 32768, 0, 2392)
('temp_data.csv', 32768, 0, 820)

Теперь давайте создадим директорию с именем dir: os.mkdir('dir'). Если такая директория уже есть, то получим сообщение об ошибке. Если все в порядке, то директория будет создана. Теперь повторим вывод функции ilistdir()

('boot.py', 32768, 0, 252)
('init.mpy', 32768, 0, 225)
('lcd_api.py', 32768, 0, 6882)
('esp8266_i2c_lcd.py', 32768, 0, 3293)
('mfrc522.mpy', 32768, 0, 2392)
('temp_data.csv', 32768, 0, 820)
('dir', 16384, 0, 0)

Как видно, директория dir создалась.

В файловых системах есть такое понятие как путь. Это последовательность вложенных директорий от корня файловой системы до какого-либо файла или директории. Давайте посмотрим путь до текущей директории:

Exp43-3.py
  1. import os
  2.  
  3. uos.getcwd()

Результат:

'/'

Текущей директорией является / - это значит, что мы находимся в корне файловой системы. Давайте перейдем в недавно созданную нами директорию dir и повторно выведем текущую директорию

Exp43-3.py
  1. import os
  2.  
  3. os.chdir('/dir')
  4. uos.getcwd()

Результат:

'/dir'

Это значит, что мы перешли в директорию /dir и сейчас она является текущей директорией. Если мы сейчас запросим список файлов, то получим пустой ответ так как в директории /dir у нас нет файлов. Мы можем получить список файлов в корне или в другой директории, если укажем конкретный путь, например:

files = os.listdir('/')

Вернемся обратно в корень файловой системы и удалим директорию dir:

Exp43-4.py
  1. import os
  2.  
  3. os.chdir('/')
  4. os.rmdir('dir')

Директорию нельзя удалить, если в ней есть вложенные файлы или директории. Сначала нужно удалить их. Если все в порядке — директория удалится. Если сейчас запросить список файлов в корне, то увидим, что директории dir больше нет.

Также мы можем удалить файл

uos.remove('filename')

или переименовать файл

uos.rename('old_name', 'new_name')