Help please with Syntax to read SD card files

HI All,
I need help please, with how to make a command, to read the files on my SD card.
I make a list of the file names in a function …

 void Get_SD_Names(const char * path) {
   SD_ONbus();
   X = 0; 
   File root = SD.open("/"); 
       while (true) { 
           File entry = root.openNextFile();
           if (!entry) {
             break; 
           }
           Song_Name[X] = entry.name(); 
           entry.close();
           X++; 
       }
   root.close();
 }

Song_Name[X] is defined as a string at start of my code … String Song_Name[50];
I can then show a list of the file names Song_Name[X] on my TFT touch screen.
I then have Song_Name[X] buttons, to read the contents of whichever file is selected.

Problem … the names I get are like this “File1.txt” , “File2.txt” , etc … NOT like this “/File1.txt”
When I press a button and then call my “read file contents” functin …
void Read_File_Contents(const char *path) {
… I need to add the “/” to the beginning of the file name, to make a path i.e “/File1.txt”

If I manually use Read_File_Contents("/File1.txt"); it reads the file OK.

However, when I press a button, I need to automatically make a command, somehow like … Read_File_Contents("/" + Song_Name[X]);
… depending which button is pressed, but that doesn’t compile.

How do I combine the “/” onto the string name Song_Name[X] to make a command
Read_File_Contents("/path"); ??
Or, how to read each Song_Name[X] string as the “path” … not just the “entry.name()” ??

Thank you,
Trevor

Take a look at

Things changed:

  • removed while (true)-loop
  • using std::vector as return type instead of using a fixed size global array
  • take the path parameter into account. The function can now be used for different paths on the SD-Card

Thanks Boris again,
I’ll read and work through.
I’m still not sure what the command looks like, to access my function Read_File_Contents(“/path”); to read one file contents ?

Please share your Read_File_Contents function.

Thanks Boris

void Read_SongFile(const char *path) {
  SD_ONbus();
  Midi = 0; 
  //open song file ---------------------------------------------------------------------------------------------------------------------------
  Song = SD.open(path);                               //open the file
  if (Song) {                                                   //song open ???
    // GET ALL chord numbers now -------------------------------------------------------------------------------------------------------------
    while (Song.available()) {                            //loop is ONCE PER CHORD, until end of file
      Chord_count = Song.read();                      //at last chord = total number of chords in song
      Chord_count = ((Chord_count) - '0');            //ASCII to DECIMAL
      Song.read();                                             //space
      //read chord MIDI numbers ---------------------------------------------------------------------------------------------------------------
      Read_MIDI_number();                             //READ CHORD #X  = 3 MIDI Note Numbers
      Read_MIDI_number();
      Read_MIDI_number();
    }
    Song.close();                     //finished - got all chords in song, close the file -------------------------------------------------------
  }
}

I’ve truncated this to simplify here, because there’s much more data in files being read.
This reads a text file’s data, which has a series of chords to play on a MIDI keyboard.
I need to call this function, from knowing the “Song_name” String, but the compiler errors are
"error: cannot convert ‘String’ to ‘char*’ ".
Somehow I need the call to include the char “path” (“/Song_name”)

Your function has a const char* parameter, but your song name is of type String. You can use the c_str() function of the String class:

Example:

  String filename = "/myfile.midi";
  Read_SongFile(filename.c_str());

Thanks Boris, I’ll try that.
Can I change the function

void Read_SongFile(const char *path) {

to use a String instead of const char ?

Does this mean I have to have the text “/myfile.midi” in my code ?
I’m getting confused now, until my code reads the SD card, it won’t know the file names.
This is my problem, all the examples show how to read a file called “File1.txt”. But I won’t know the file names until after the card is read.
I want to click on the file name on the touchscreen list, to read that file.
Thanks Boris

No, that was just an example on how to use the .c_str() function from a String object to obtain the const char* which is required by your function.

The names are correctly (with the leading path) stored as String objects in the vector.

Thanks Boris, I’ll let you know how I get on

Just trying to get the idea straight in my head.
So I’ve defined …

String Song_Name[50];

Then I read SD card to get names, as strings (up to 50 names).
I’m still confused how to get from my string Song_Name[50] to the line below

Read_SongFile(filename.c_str());

Is it ? … Read_SongFile(Song_Name[X].c_str());

X is the number of the button I click on the touchscreen.

Yes, that’s correct :slight_smile:

Thanks Boris, I understand better now.
Still my biggest problem as a beginner, is working out what commands and data types to use and how to change things to do what I want.
Everything I’m doing is picking bits from online examples and working out how to implement those ideas for myself. A lot of “trail and error” with no formal training.
“Thank the lord, for Boris” :grin:

Got it working !
Boris, you got me there, almost, thank you.
To summarise …

My function to give me a list of SD card files, is now …

void Get_SD_Names(const char * path) {
  SD_ONbus();
  X = 0;                                  // 0 = SYSTEN VOL INFO folder....  so 1 = SONG 1
  File root = SD.open("/");               // Open the SD card, to read file names
      while (true) {                      // LOOP, while there are still more entries on SD card ......
          File entry = root.openNextFile();
          if (!entry) {
            break;                        // break = root.close(), if no more files ???
          }
          Song_Name[X] = entry.name();    // store each entry name to a SONG name
          Song_Path[X] = entry.path();
          entry.close();
          X++;                            //next file entry name
      }
  root.close();
}

I’ve defined uint8_t X; a single byte number variable.
I’ve defined String Song_Name[50]; up to 50 file names, for my TFT touchscreen buttons.
I’ve defined String Song_Path[50]; up to 50 paths to the files on the SD card.

I show a column of buttons on the screen, each with a number X and a text label Song_Name[X];

So, when I press button 6 (for example), X=6 and my code calls …

Read_SongFile(Song_Path[X].c_str());

… to read data from the SD card path “/file number 6”.

Then this function (simplified version) reads the file’s data …

void Read_SongFile(const char *path) {
  SD_ONbus();
  Midi = 0; 
  Song = SD.open(path);                               //open the file
  if (Song) {                                                   //song open ???
    while (Song.available()) {                        //loop is ONCE PER CHORD, until end of file
      Chord_count = Song.read();                 //at last chord = total number of chords in song
      Chord_count = ((Chord_count) - '0');    //ASCII to DECIMAL
      Song.read();                                          //a space (discard)
      Read_MIDI_number();                          //READ CHORD [X]  = 3 MIDI Note Numbers
      Read_MIDI_number();
      Read_MIDI_number();
    }
    Song.close();                     //finished - got all chords in song, close the file -------------------------------------------------------
  }
}

Then, I get a screen on the TFT to manage playing the series of chords, on my MIDI keyboard.
The “SONG NAME” at the top.
Then, “NEXT Chord”, showing the chord (i,e, “A# Major”) … ready to play.
Then a “PLAY” button, which plays the chord, for as long as I hold the button.
When I release “PLAY”, the next chord is loaded, ready to play.

All looking great now !
Many thanks to Boris (sivar2311) who has helped me a lot.
Trevor