Read filename from SD card, store to a string

Why do you want to see my MP3 player code, when its not related to the question I am asking.
I could have a new project with no code, and I want to read the file name using the SDFAT library, and there would be no code to post.

The only thing relating to opening a file is the part I posted above, which is directly out of the example from the SDFAT library, I have gotten no where further than that.

Why do you want to see my MP3 player code, when its not related to the question I am asking.

Because I assumed that you had tried something, and failed, or hit a wall, or something. So I was wrong. Sue me.

:~

Not enough sleep at my end I think.

Everything I have tried I have posted. All I am trying to do is find the function or the method to read the file name using the sdfat library.

I have just searched the sdfat library and cant find a function called available()

while(file.available() > 0)

Where is this from?

WanaGo:
I could have a new project with no code, and I want to read the file name using the SDFAT library, and there would be no code to post.

If that was the case, you would have been wasting everyone's time by asking for help before you had made any attempt to solve the problem for yourself.

If this problem is a small part of a complex sketch then write a new sketch which demonstrates the problem in the simplest possible way. You will find this often helps you to make progress on the problem yourself since it forces you to test assumptions about which parts of your code are relevant to the problem.

In this case you want to open the directory (using SD.open()), access each file in turn (using File.openNextFile()) and get the file name (using File.name()).

If you know the file name includes a decimal number and want to know what the number is, you need to parse the number from the string. The C runtime library provides various functions such as atoi() to do that sort of thing.

This does not look terribly difficult and I would have thought you could at least have a stab at it before you give up and ask for help. Showing us your attempt would also show us which parts of this problem you have solved and which parts are causing you trouble, so the people trying to help you aren't left trying to solve the whole problem for you from scratch, which seems to be the situation at the moment.

I have this, which I posted above

// open next file in root.  The volume working directory, vwd, is root
  while (sdCardFile.openNext(sdCard.vwd(), O_READ)) 
{
  MaxFiles++;
    
  sdCardFile.close();
}

And I essentially want to do something like this:

// open next file in root.  The volume working directory, vwd, is root
  while (sdCardFile.openNext(sdCard.vwd(), O_READ)) 
{
  MaxFiles++;
  sdCardFile.printName(??) //But I dont want to print to a serial stream, I want to print to a int, or a string
    
  sdCardFile.close();
}

Cheers

I appreaciate that, but I have posted what I tried.

I didnt just go and write code I know wouldnt work, I tried looking at the sdfat library first to find a function which was suitable, but I havent found one that I understand how to use, hence the post...

There is no more code to post as I havent written any....

Im confused why this is so much of an issue... should I be trying stuff I have no idea if it will work, or should I be reading the library to find something suitable first. I thought the 2nd option was the valid option here...

Sorry if I have offended anyone, but I just havent written non working code, would like to find a viable solution from the library first...

In this case you want to open the directory (using SD.open()), access each file in turn (using File.openNextFile()) and get the file name (using File.name()).

This is what I am essentially doing, but I cant find the name() you are speaking of...

Crap ok, found it.

I was using these:

//Add the SdFat Libraries
#include <SdFat.h>
#include <SdFatUtil.h>

not the base SD library.

I see available() now too.

Thanks

Where is this from?

Left field. I thought you were trying to read the name FROM a file, not the name OF a file.

WanaGo:
Crap ok, found it.

I was using these:

//Add the SdFat Libraries
#include <SdFat.h>
#include <SdFatUtil.h>

not the base SD library.

I see available() now too.

Thanks

If you'd posted your actual code (in its entirety), we'd have known that.

I did say in post #1 I am using the SDFAT library, not the SD library. Also posted pieces of the SDFAT functions. I didnt even know there was a SD library 'wrapper' or whatever its called to be honest.

Tried implmenting the SD library instead, but its not compiling. Looks like the 2012 SDFAT library I am using is not quite the same as the 2009 SDFAT library which is part of the SD library included with Arduino 1.01

No luck so far, will keep trying.

It's easy to find excuses not to, or reasons why we should have guessed or noticed some quirk of your solution, but there's simply no substitute for posting your actual code when you need help with a coding problem.

I'm a real noob, so don't jump on me as I haven't written any code.
I'm looking for a sample of code to do exactly what the OP was trying to do but I stumble into too many issues over creating a dynamic string array and reading each file name. There are too many libraries and I'm not a programmer. I'd appreciate some help.
I need a simple sketch that creates a character array, opens the root directory, reads the names and appends them to the array to allow it to be read and accessed later. This will be used to play .wav files from the card. I have code to read a named .wav file and play it from the SD card but this string manipulation part of the project eludes me.
I have looked at the CardInfo example but can't understand how to move the read list to a script. I've tried to modify the openNextFile example on the arduino reference site, but can't go from printing the file names to adding them to a script. I'm sure that this is simple but it's beyond me.
I know I'm asking for someone to post a short sketch for me, I do hope people don't find this offensive, but I am lost.

Thanks in advance

Shane

Probably should start another thread at this point, but this question is the same as the OP. Which I assume needs to be corrected to "read filename from SD card, initialize to a new array"

Here is some code demonstrating a async function (called every loop when active) in attempt to be created.
The challenge is accessing the returned (string/array?) as an array to deal with the letters of the filename independently. This way I can serve them to my haptic display to a user that types "ls" ala unix cli style.

void ls(boolean activate){  // list contents of working directory
  static boolean active = false;
  static File contents = workingDir.openNextFile();
  static byte index = 0;

  if(activate){ // given a 'true' is passed to ls it gets called every loop
    active = !active;
    if(!active){
      index = 0;
      contents.close();
      contents.rewindDirectory();
    }
  }

  if(active){ // when active 'ls' gets called every loop
    if(extHapticMessage(MONITOR_MODE)){  // returns true on complete letter
      if(contents){                      // given a file
        char name[15] = contents.name(); // <- problem: I dont know the size!
        if(name[index]){                 //
          extHapticMessage(name[index]); // vibrates an series of pagers
          keyOut(name[index]);           // prints letter w/ keyboard emulation
          index++;                       // iterate index for when pagers finish 
        } else {                         // when filename is printed 
          index = 0;                     // reset index
          if(contents.isDirectory()){keyOut('/');}  // trail a slash given dir
          contents.close();              // gracefully close the file
          keyOut(CARIAGE_RETURN);        // prepare to print next filename
          contents = workingDir.openNextFile();  // open next file
        }
      }
    }
  }
}

I apologize about my commenting style, I always make the assumption there is a syntax highlighter

This does not compile because the compiler wants to the the array (name[]) initialized to a brace-enclosed initializer. Which I can understand, it wants to know the size of what it is getting.

Is there an better way to directly access what (file).name() returns? Maybe in a way I can pick off the individual letters at a time? (file).name() Seems to pass to Serial.println() a char array without much fuss.

        char name[15] = contents.name(); // <- problem: I dont know the size!

The value that the name() method returns is a pointer to a string. Is it the size of the pointer that you don't know (2 bytes) or the length of the string pointed to? If it's the latter, strlen() can help.

Or, strdup() will use malloc() to allocate space, and return a pointer to the duplicated string. You'll need to free() that memory when you are done with it.

Does the SD class support anything other than 8.3 format names? Don't you really already know the maximum length of the string?

Do you understand that that allocation and assignment will fail, since you can't assign a pointer to char array?

PaulS:
Is it the size of the pointer that you don't know (2 bytes) or the length of the string pointed to?

in reference to the comment-> // problem: I don't know the size
Scratch that. This was a comment out of ignorance, assuming the compiler needed to know the size of the a returned array that I now know isn't being returned.
An assumption rooted in seeing the function used like this -> Serial.println(myFile.name()) // no ref entry for .name()

PaulS:
Does the SD class support anything other than 8.3 format names? Don't you really already know the maximum length of the string?

Good point, so a max of 13 chars right? (8 for the name, one for the period, 3 for the extension, 1 for null)

PaulS:
Do you understand that that allocation and assignment will fail, since you can't assign a pointer to char array?

Thought it was returning the char array itself.

Guess bringing the string into another part of memory would be redundant if we have address to where it is already stored in memory. Please correct me if my understanding of pointers is wrong I haven't normally used them.

To exemplify my ignorance a little further I have to ask the question, does the name() returned pointer refer to an address on the SD card or one that has been loaded into ram already? (my assumption is ram because only 2 bytes are returned) In either case how would I go about addressing it in my function?

All I really need to is read each individual letter in the filename. Having the whole string at any given time is irrelevant to the function working so I don't really want to allocate memory for the whole string if I can avoid it. Every loop where a new letter is needed from the filename, myFile.name() will be called, at least in the way this function is used.
In that case can I just point to the next byte after the pointers address to get the second letter in the array?

Maybe I'm missing the concept completely or maybe seeing code examples would help would give me an ah ha moment.

Ok, I think I came up with the solution

void ls(boolean activate){  // list contents of working directory
  static boolean active = false;
  static File contents = workingDir.openNextFile();
  static byte index = 0;

  if(activate){ // given a 'true' is passed to ls it gets called every loop
    active = !active;
    if(!active){
      index = 0;
      contents.close();
      contents.rewindDirectory();
    }
  }

  if(active){ // when active 'ls' gets called every loop
    if(extHapticMessage(MONITOR_MODE)){  // wait till letter is complete
      if(contents){                      // given a file
        char* name = contents.name();    // intilize pointer to array
        if(name[index]){                 // test for a char
          extHapticMessage(name[index]); // vibrates an series of pagers
          keyOut(name[index]);           // prints letter w/ keyboard emulation
          index++;                       // iterate index for when pagers finish
        } else {                         // when filename is printed
          index = 0;                     // reset index
          if(contents.isDirectory()){keyOut('/');}  // trail a slash given dir
          keyOut(CARIAGE_RETURN);        // prepare to print next filename
          contents.close();              // gracefully close the file
          contents = workingDir.openNextFile();  // open next file
        }
      }
    }
  }
}

tl;dr -> char* name = myFile.name()
Creates a pointer (physical address to the first byte of the array) that can be accessed like an array

Seems to work as expected, now to debug the more heuristic issues with my code. Thanks

Guess bringing the string into another part of memory would be redundant if we have address to where it is already stored in memory.

That pointer will be overwritten when the next file is accessed. If you are creating a list, you need to copy the data.

To exemplify my ignorance a little further I have to ask the question, does the name() returned pointer refer to an address on the SD card or one that has been loaded into ram already?

SRAM.

In either case how would I go about addressing it in my function?

I see that you've figured that out.

In that case can I just point to the next byte after the pointers address to get the second letter in the array?

Yes. The index is an offset added to the address that the pointer points to to get to where the real data is.

Creates a pointer (physical address to the first byte of the array) that can be accessed like an array

Yes. Perhaps the above comment explains why that works. There is a very close association between arrays and pointers. Once you understand that, and that you must actually make a pointer to to somewhere, your there with understanding pointers.

Next step: Pointers to pointers and pointers to functions.

PaulS:
That pointer will be overwritten when the next file is accessed. If you are creating a list, you need to copy the data.
SRAM.

Which is fine in this case. ls() just streams out the data. Maybe if I want to have a utility to select a file though, I can see where I may need to create a static array of pointers. Although that wont help if its just putting the filename in a buffer. Honestly its probably not that process intensive just to go back and read it every time needed instead of allocating some huge buffer that there is no room for.

With my application the user can only be shown so much information at a time anyhow.

I'm not sure about pointers to pointers right now, but pointers to functions may start to come in handy once I create mkdir(),cat(),rm(),cd(),cp(),mv() and so forth.