SDFat error file.open and what does it really mean for a file to be 'open'

The analoglogger example for sdfatlib creates 100 unique log files of the form LOGGERnn.CSV before wrapping around and clobbering the earliest file.
ie

  for (uint8_t i = 0; i < 100; i++) {
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

Ideally I would like the filename created in my application to be the date of today’s log. However since the log files have a creation date (or is it modification date?) when viewed in a desktop OS then having a sequence of log files that don’t contain the date as their filename will suffice until my understanding of C improves.

In attempting to create not 100 unique but 1000 unique log files (ie several years worth of daily logs) I modified my sketch, which borrows heavily from analoglogger thusly:

  char name[] = "LOGGE000.CSV";

  for (uint16_t i = 0; i < 1000; i++) {
    name[5] = i/100 + '0';
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

Upon every reset a new log file is created. Everyone is fine until after LOGGE099.CSV - then to my surprise rather than getting LOGGE100.CSV I got

Logging to: LOGGE1:1.CSV

echoed to the terminal.
Obviously there is a beginners error in my code which any experienced C programmer will be able to correct but what I think might be more revealing is that continuing to reset my target board produced log files up to:

Logging to: LOGGE1:9.CSV

and then I received a file.open error - presumably as the file name wraps around.

I had always always thought that fat16lib’s extensive error trapping throughout the analoglogger sketch was a little overboard and made the code harder to follow but this shows why it is important.

The more interesting and abstract question that my hamfisted coding might give someone the opportunity to comment on is what does it really mean for a file on an SD card to be ‘open’ in the Arduino environment.

Is this just a concept that the AVR has of while data that is in static RAM that has yet to be written out or is the concept of being open something that the SD card itself has in an index stored on the card, or is there a flag against the file itself that
logfile.is_open()) is reading.

What is, to me, equally interesting is what these ‘open’ files look like from the point of view of the desktop OS

presumably the colon is replaced with a slash as by the OS but you can see that the files have no modification date and furthermore can’t be moved to the trash due to error

The operation can’t be completed because one or more required items can’t be found.
(Error code -35)

However since the log files have a creation date (or is it modification date?) when viewed in a desktop OS then having a sequence of log files that don't contain the date as their filename will suffice until my understanding of C improves.

The date may well be meaningless, as the Arduino doesn't really know what time it is. If you add some mechanism (RTC, ethernet connection, link to PC) so that it does, the SD class doesn't know that the Arduino knows what time it is.

Upon every reset a new log file is created. Everyone is fine until after LOGGE099.CSV - then to my surprise rather than getting LOGGE100.CSV I got

No surprise, really:

    name[5] = i/100 + '0';
    name[6] = i/10 + '0';
    name[7] = i%10 + '0';

i = 100, so i/100 is 1. 1 + '0' is '1'.
i/10 is 10. 10 + '1' is?
i%10 is 0. 0 + '0' is '0'.

Try again. Think i%100/10.

presumably as the file name wraps around.

No. You get the error because the name contains an invalid character.

OK Thanks Paul,

I have successfully modified my analoglogger derivative to make more than 100 log files as per:

  char name[] = "LOGGE000.CSV";

  for (uint16_t i = 0; i < 1000; i++) {
    name[5] = i/100 + '0';
    name[6] = i%100/10 + '0';
    name[7] = i%10 + '0';
    if (sd.exists(name)) continue;
    logfile.open(name);
    break;
  }
  if (!logfile.is_open()) error("file.open");

and without wishing to disappear don’t the rabbit hole with this can you elaborate on why

name[6] = i/10 + '0';

(which evaluates to 11) causes a colon to be output in the filename echoed to the terminal. 11 is not the ASCII character code for a colon, is it simply that if you feed a 2 character alphanumeric string into name[6] the output is ambiguous because you want to select a single character ?

and without wishing to disappear don't the rabbit hole with this can you elaborate on why

name[6] = i/10 + '0';

(which evaluates to 11) causes a colon to be output in the filename echoed to the terminal. 11 is not the ASCII character code for a colon

When i is 100, i/10 is 10. '0' is 48 in the ASCII table. 10 + 48 is 58. Not surprisingly, 58 in the ASCII table is ':'.

I don't know how you figure that 10 + '0' is 11. It's your turn to explain.

Sorry Paul I meant that 11 is the answer to the question posed in your second last post

i/10 is 10. 10 + '1' is?

Sorry Paul I meant that 11 is the answer to the question posed in your second last post

But, it isn't. 10 + 1 is 11. 10 + '0' is 58. 58 is ':'.

(The + '1' was a typo; it was supposed to be + '0')

OK I now understand that the C statement:

char[6] = i/10 + '0'

simply converts between a single digital decimal number 'i' and it's equivalent ASCII character code (necessary to build a filename in a character array) by adding (decimal) 48 to each number between 0 and 9.

This works because the ASCII character code for the characters '0' through '9' are ASCII 48 to 57

The colon character ':' is ASCII 58 which is the first thing you hit if drive out of the numerals and into non alphanumeric territory in the ASCII table.