Creating and Displaying an Array of Strings

This program requires me to read an sd card that contains a bunch of folders, I then need to save the names of each folder into an array. After that, I need to display the names on a screen and allow the user to scroll through them and select them.

my current solution is so slow it takes 4 seconds to load the list so I’m looking for an alternative.

Currently, I read each file as a String and combine them all as a single String with each name separated by a ^. These Strings are the String class.

This was the only way I could the list to leave the function, I tried and char, char*, and a char** but it still didn’t work.

Another problem we ran into was that when we tried to read a file name that was over 8 characters it was abbreviate it to 6 characters with a ~1 on the end.

The solution to that was to just store the name of the folder inside a text file, called name.txt, in the folder. But I sure that causes quite a lot of load time.

Here is that code.

String Files::getDirList(char* path)
{
  Serial.println("current path: " + String(path));

  File dir = SD.open(path);
  String list = "";
  while (true)
  {
    File entry =  dir.openNextFile();
    if(! entry && list == "")
    {
      Serial.println("empty directory");
      return "ERROR";
    }
    else if (! entry) 
    {
      Serial.println("no more files");
      break;
    }
    if(!entry.isDirectory())
    {
      Serial.println(String(entry.name()) + " is not a directory");
      continue;
    }
    
    File oldDir = dir;
    
    String newPath = String(path) + String("/") + (String)entry.name() + String("/name.txt");
    File nameFile = SD.open(newPath);


    String name = "";
    while(nameFile.available())
    {
      char ch = nameFile.read();
      name += ch;
    }
    list += name + "^";
    nameFile.close();


    entry.close();
  }


  Serial.println("list filled");
  return list;
}

This is the function I use to pull a name from the long string

String Files::grabFile(String file, int position)
{
  int cCount = 0;
  String string = "";
  for(int i = 0; i <file.length(); i++)
  {

    if(file[i] == '^')
    {
      cCount++;
      continue;
    }
    if(cCount == position)
    {
      string += file[i];
    }

  }
  return string;
}

Here is the function that prints the text.

enum Color {RED, GREEN, BLUE, BLACK, WHITE};// pulled from class definition 
void List::displayItem(Ucglib_ST7735_18x128x160_HWSPI* screen, ucg_fntpgm_uint8_t* font, List::Color color, int x, int y, String text)
{
  screen->setFont(font);
  screen->setPrintPos(x,y);
  changeColor(screen,color);// calls the function below
  screen->print(text);
}
 void List::changeColor(Ucglib_ST7735_18x128x160_HWSPI* screen, List::Color color)
 {
   
   switch(color)
   {
      Serial.println("entering switch");
      case BLUE:
        screen->setColor(0,0,255);
        Serial.println(color);
        Serial.println("setting to blue");
        break;
      case RED:
        screen->setColor(255,0,0);
        Serial.println("setting to red");
        break;
      case GREEN:
        screen->setColor(0,255,0);
        Serial.println("setting to green");
        break;
      case WHITE:
        screen->setColor(255,255,255);
        Serial.println("setting to white");
        break;
      case BLACK:
        screen->setColor(0,0,0);
        Serial.println("setting to black");
        break;
      default:
        screen->setColor(255,255,255);
        Serial.println("Running default");
        break;
   };
 }

Just creating the list string takes a few seconds and printing 15 names to the screen adds up to a total of 4 seconds.

There must be a better way of doing this, one that also fixed the weird abbreviation ~1 problem.

If anyone could give me an idea that would be great. If there is another approach to reading the files, saving the files, and displaying the files, I would love to hear it. I am willing to completely rewrite everything as long as I can lower the load time significantly.

if your files are composed of multiple lines ending terminated with line feeds would readStringUntil() be helpful?