Чтение из SPIFFS - Как лучше всего работать со строковым (или char) массивом с неопределенной длиной?

Я читал, что лучше всего избегать использования строки в Arduino, поэтому я готов использовать массив символов, если это лучше. Я читаю имена файлов с SD-карты, и моя цель-сохранить их в массиве, а затем прочитать этот массив. В настоящее время я делаю следующее:

String lib_arr[100];
int lib_arr_size;

а потом

File dir = SD.open("/");
int c = 0;
while (true) {
  File entry = dir.openNextFile();
  if (!entry) {
    // Если больше нет файлов
    lib_arr_size = c - 1;
    break;
  }
  if(strcmp(entry.name(), "SYSTEM~1") == 0) {
    continue;
  }
  lib_arr[c] = entry.name();
  entry.close();
  c++;
}

а потом

for (int i = 0; i < lib_arr_size; i++) {
  if(i == pos) {
    tft.print("> ");
    tft.println(lib_arr[i]);
  } else {
    tft.println(lib_arr[i]);
  }
}

Это не решение, потому что для моих целей строка lib_arr[100] может быть 1000 или 10000 или 100000... и я обнаружил, что, увеличивая это значение, глобальные переменные используют skyrockets, и Arduino говорит, что у него не хватает памяти. Моя цель - оптимизация памяти. Я не знаю, как решить эту проблему.

, 👍-1

Обсуждение

чтение и печать/обработка на одном дыхании. не храните список в памяти. здесь у меня есть SD браузер https://github.com/jandrassy/lab/blob/master/SDWebServer/SDWebServer.ino, @Juraj

@Juraj Это отличная идея! Но когда я просматриваю, всякий раз, когда я поднимаюсь или опускаюсь, чтобы выбрать разные файлы, мне придется каждый раз идти на SD - карту и получать файлы. Не повредит ли это памяти? Это хорошая практика? Это лучше, чем хранить в массиве?, @JingleBells

Библиотека SD использует эти старые имена файлов "DOS" в формате 8.3 с автоматическим переименованием. Это а) ограничивает необходимый размер и б) делает бесполезным иметь дело с 10 000 файлов сразу, так как они будут иметь неузнаваемые имена..., @DataFiddler

у вас нет оперативной памяти для кэширования имен. но у вас есть время, чтобы загрузить их. на MCU с большим количеством оперативной памяти вы могли бы кэшировать какую-то последнюю виденную папку, но это было бы преждевременной оптимизацией, и это корень всего зла в кодировании. https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize, @Juraj

@Juraj Значит, я должен получить и прочитать имена файлов на каждом выбранном файле?, @JingleBells

почему нет? он не медленный и ничего не потребляет, @Juraj

@Juraj Все понял. Спасибо!, @JingleBells


2 ответа


0

Ну, вы не можете использовать больше памяти, чем у вас есть. Если длина имен файлов (вероятно/возможно) слишком велика, вы просто не можете сохранить ее в памяти. Некоторые альтернативы:

  • Используйте некоторое сжатие... Это немного сэкономит вам время, но в конце концов, если вы не знаете, сколько максимальных байтов вам нужно сохранить, это не сильно поможет
  • Используйте внешнюю память SRAM... Вам нужно написать свои собственные функции памяти. Также небольшое повышение производительности.
  • Используйте память SD-карты... Как SRAM, но гораздо медленнее. Также не уверен, что вы можете использовать одну и ту же SD-карту для записи.
  • Лучшим решением, но оно может значительно снизить производительность, является не сохранение всех имен файлов, а просмотр имен файлов и обработка того, что вам нужно по пути. Однако это не всегда возможно или выполнимо. В вашем решении вы можете распечатать имена файлов напрямую, не сохраняя их (но, я полагаю, вы хотите выполнить некоторую дополнительную обработку).
,

Например, пользователь может создать 10000 файлов с одним символом в каждом., @JingleBells

Я могу себе представить, но вы все равно не можете запомнить все эти имена файлов. Вам нужна либо внешняя память, либо обрабатывайте их по мере просмотра каждого файла (без сохранения промежуточных данных/результатов)., @Michel Keijzers


0

Пожалуйста, загляните в библиотеку SPIFFS/ LittleFS. Вы увидите, что длина файла (в этих файловых системах она включает путь и корневой индикатор"/", а также расширение .XXXXX, как в .shtml ). Максимальная длина, определенная в библиотеках, составляет 32, поскольку максимальная длина означает, что 31 символ должен использовать терминатор + 1. Всем умникам, утверждающим, что вы можете это изменить (да, вы можете, но не должны). Не делайте этого - на то есть причины. Прочитайте больше.
Максимальное количество файлов определяется размером блока, и вы определили свой раздел SPIFFS.
Нет никакой разницы между записью на SPIFFs или SD-карту, у которых есть около 100 000 циклов r/w на каждую отдельную физическую "ячейку". Иногда дешевле получить новый ESP, чем SD-карту.

Вопрос к ОП:
Пока вы читаете, нет проблем делать это часто, если вы делаете массовые переименования, у вас может возникнуть проблема через некоторое время. То, что вы делаете, на самом деле частично копирует то, что делают библиотеки - настолько они устарели. Скорость одинакова, потому что в любом случае это та же флэш-память (+ ваши накладные расходы на обработку).

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

Если вам нужны данные в другом месте (браузер) фильтр & трансляцию он - не делайте между ними хранения (=дублирование) с небольшим памяти


В качестве заключительной мысли из технических спецификаций:

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

Флэш-устройства SPI физически разделены на блоки. На некоторых флэш -устройствах SPI блоки дополнительно разделены на сектора. Спецификации иногда назовите блоки секторами и наоборот.

Общие емкости памяти для flash SPI составляют от 512 КБ до 8 МБ данных, где блоки могут быть 64 КБ. Секторы могут быть, например, 4 Кб, если поддерживаются. Многие Flash SPI имеют равномерные размеры блоков, в то время как другие имеют неоднородные размеры - последнее означает, что, например, первые 16 блоков имеют размер 4 Кб, а остальные-64 Кб.

Вся память линейна и может быть прочитана и записана в произвольном доступе. Стирание может быть выполнено только по блокам или секторам; или по массе стирать.

,