greiman/SdFat-beta

getFile returns SFN

Opened this issue · 13 comments

Hello,
I'm going to replace the old SdFat library on my project. (STM32 Rogers Core).
So far so good, after changing write/readBlocks to write/readSectors it works, BUT:
in SdFatConfig.h:
#define USE_LONG_FILE_NAMES 1
in my code:
file.getName(xstring, 20);
returns the SFN only. (like "BIBIUN~1")

Did I missed something?

regards
Matthias

The default is LFN with:
#define USE_LONG_FILE_NAMES 1

Modify the OpenNext example like this at about line 87

 //    file.printName(&Serial);   << remove this line
    char str[50];           // ADD
    file.getName(str, 50);  // ADD
    Serial.print(str);      // ADD

Here is the result with some test files.

Type any character to start
         0 2019-05-07 10:43 System Volume Information/
        65 2014-11-11 10:14 With.Two dots.txt
       151 2014-11-14 11:29 A long name can be 255 characters.txt
        45 2014-11-11 10:03 LFN,NAME.TXT
       186 2014-11-11 10:14 lower.txt
       188 2014-11-11 10:14 MIXCASE.txt
       184 2014-11-11 10:14 mixed.TXT
        67 2014-11-11 08:57 Not_8_3.txt
        30 2014-11-11 08:54 OK%83.TXT
        33 2014-11-11 08:59 STD_8_3.TXT
        59 2014-11-11 09:59 With Blank.txt

Unicode is only supported for exFAT as I stated in a previous post. You can format small SD cards with the ExFatFormatter example, it forces exFAT format. You can also format small cards exFAT on a PC with Linux, Windows, or a Mac.

Try the ExFatUnicodeTest example. It requires this setting:
USE_UNICODE_NAMES must be nonzero in SdFat/src/ExFatLib/ExFatCongfig.h

Since Arduino does not support printing Unicode, you will need to check the name on a computer that supports Unicode. Here is the name.

Euros € test.txt

Ok, thank you for your reply. Now it works, I must have forgotten something in my master code (hundreds of lines to check...).
Unicode for EXfat works either, but the restrictions are to many to switch it on my project for now.
So, the thread can be closed, because it's sure a mistake of mine.

I have just one last simple question:
I want to change the directory by index and not by char*
So I know that the file index of my "MP3/" folder is 19.
I have:
SdExFat sd; ExFile dir; ExFile file;
I'm now at root:
if (!dir.open("/MP3/")){ error("dir.open failed"); }
Works as expected.
But changing to index: ("19" is the index got with file.dirIndex() )
if (!dir.open(&dir,19,O_READ)){ error("dir.open failed"); }
gives the error condition.

So here is my question:
Isn't it possible to open/change a directory by index number?
(necessary avoiding unicode file-/directory names)

EDIT:
Ok, I found a (dirty) way, opening subdirs by index, but either you'll need many "ExFiles" or you need to do it into a circle (so you need at least 3 of them: Dir, Subdir and File):

SdExFat sd;
ExFile dir;
ExFile file;
ExFile subdir;
ExFile subdir2;
ExFile subdir3; // and so on

void setup() {
  Serial.begin(9600);
  if (!sd.begin(SD_CONFIG)) {
    sd.initErrorHalt(&Serial);
  }
  dir.open("/MP3/");
 if (!subdir.open(&dir,19,O_READ)){ // "19" is an example for a dir index inside "/MP3"
    error("dir.open failed");
  }

  Serial.println("Index:");
  Serial.println(dir.dirIndex());

  while (file.openNext(&subdir, O_RDONLY)) {
    Serial.print( file.dirIndex  () );
Serial.print (" ");
    file.printFileSize(&Serial);
    Serial.write(' ');
    file.printModifyDateTime(&Serial);
    Serial.write(' ');
    file.printName(&Serial);
    if (file.isDir()) {
      Serial.write('/');
    }
    Serial.println();
    file.close();
  }
  if (dir.getError()) {
    Serial.println("openNext failed");
  } else {
    Serial.println("Done!");
  }
}

1000 Thanks
Matthias

So here is my question:
Isn't it possible to open/change a directory by index number?
(necessary avoiding unicode file-/directory names)

How can you know the index of a file without opening it by name? The index is not a file index it's a directory entry index.

A file uses several directory entries in a contiguous group. The size of the group depends on file properties.

There may be unused entries between files.

I can get the directory entries with openNext and dirIndex, so I got back, as example:
"Mai Cocopelli - Einmal Weltraum und zur?ck.mp3", 8 (8= file index)
real Name : "Mai Cocopelli - Einmal Weltraum und zurück.mp3"
There is no chance opening the file by name caused by "... zurück" - So I need the index.
Same for folders: Example:
"Österreichische Musik/"
There is no way in the library opening by name or short name, because it begins with "?":
"?sterreichische Musik/" so I need the index number of this folder to open it - again with openNext and dirIndex
The whole code is here:
https://github.com/madias123/STM32duino-RFID-Mp3-Player/blob/master/MP3-player-beta_SH1106_17/SD_Card.ino
this part of code:
` while ( file.openNext(&dirFile, O_READ) && dir_numbers_entries < dirfilecounter) { // getting number of MP3 subfolders

if (  !file.isHidden()) { // avoid hidden files
  if (!(dironly && !file.isDir())) {
    file.getName(xstring, 20); // get only 20 chars from each file name
    // file.getSFN(xstring ); // better alternative get 8.3 filename? saves RAM
    dirIDlist[dir_numbers_entries] = file.dirIndex();
    xstring[0] = toupper(xstring[0]); // upper case the first char
    dir_numbers_entries++;
    fileName[dir_numbers_entries - 1] = (char *)malloc(22);
    sprintf(fileName[dir_numbers_entries - 1], "%s", xstring); // adding the temp. xstring to the char array
  }
}
file.close();

}
`
With this method the user can see the file or folder name on the display and open it.

Maybe a good future improvement would be to allow the Unicode "C1 Controls and Latin-1 Supplement".

See this chart.

These are codes 0X0080 - 0X00FF. Since they are 8-bit they could be supported in 8-bit char strings. I need to understand how Microsoft maps these to short names.

Good day. I have a similar problem with SdFat. Think you can implement unicode for FAT16 or FAT32 in the near future. Or the solution you mention in your last post. well thank you

I have no plans to expand the character set for FAT16/FAT32 in the near future.

Can you help me to solve this problem. I use your SdFat 1.1.2. When opening a file that uses special characters {Czech-Slovak}. these are replaced with {?}.

I cannot open those files by the pad, because the file names do not match. Example: (h?ll? != hello)

Loading file name: 1.(file.openNext(sd.vwd(),O_READ))
2. file.getName(filename, sizeof(filename));

//Open the file in read mode.
if(!track.open(filename, O_READ)) this does not match, because the loaded filename is not as sure as it is stored on the sd card.

Of course, for names without special characters (English texts) it works.

Could you please help me? for example, if you didn't insert {?} instead of special characters, would it work? Is it possible to modify SdFat 1.xx? Well thank you

Could you please help me? for example, if you didn't insert {?} instead of special characters, would it work?

No, the special characters must be translated to Unicode in order to open the file.

The problem is that codes 0X80 - 0XFF in 8-bit character strings represent different characters depending on the locale for your computer. I can't translate these code to Unicode.

See Locales and Code Pages.

OK so differently. I'm not interested in displaying special characters. Just that when the file with special characters load from the sd card, it was possible under the loading "name" to open for reading.
Example: name file is hello.txt , we use the read function, we get some numbers in dec. 72,101,108,108,111. The same numbers are used when opening the file.

If you use extra characters, they actually have only other numbers. example: 72,233,108,108.111
Sdfat does this by replacing the number 233 with another number (the "?" Character).
The fact that the number 233 will be represented absolutely do not mean the character, respectively, without display, does not matter.

The important thing is that the loaded "name" will be identical to the team in the file. If there is a number 244 representing some character, let it stay there and not change.

Practically, I need Sdfat to load all characters (more precisely, the numbers that represent the characters) in the range of 0x00 to 0xFF.

yes I will not assigned characters values ​​0x7F to 0xFF but it does not matter. These values ​​are assigned by the characters of the superior system or the system that displays them.

You can try the following:

Edit SdFat-beta/src/FatLib/FatFileLFN.cpp

At line 92 make these changes to lfnLegalChar()

inline bool lfnLegalChar(uint8_t c) {  // <<-- replace char with uint8_t
  if (c == '/' || c == '\\' || c == '"' || c == '*' ||
      c == ':' || c == '<' || c == '>' || c == '?' || c == '|') {
    return false;
  }
  return 0X1F < c;  // <<-- allow 0X20 - 0XFF
}

This may allow opening files for read. It must not be used to create files.

I was able to open a file with this name Héllo.txt

char name[] = {'H', 233, 'l', 'l', 'o', '.', 't', 'x', 't', 0};

character code must have these Unicode values.


Ascii characters are not larger than 7F. You must use Unicode characters.

You can use Latin-1 Supplement characters see this table.

You must use the Unicode values. That's why I entered 233 for é.