[SOLVED] Can't open file from dynamic filepath

Hi,

I've been struggling with an issue for a week now. I'm trying to read a filepath from a text file, and the open the said file.
The following code doesn't work :

SdFile prev,file;
char nextApp[30];

if (prev.open("/System/bin/NEXTAPP.TXT", O_READ))
  {
    char c = 0;
    int i = 0;
    String s = "";

    memset(nextApp, 0, 30);

    while (c != '\n')
    {
      c = prev.read();
      if (c != '\n')
      {
        s += char(c);
        nextApp[i] = c;
      }
      i++;
    }

    SerialUSB.println(strcmp(s.c_str(),"/test/test.bin")?"Match":"Differ"); // Displays "Match"
    SerialUSB.println(strcmp(nextApp,"/test/test.bin")?"Match":"Differ"); // Displays "Match" as well

    if (file.open(nextApp, O_READ))
    {
      SerialUSB.println("Success open from char *");
    }
    else if (file.open(s.c_str(), O_READ))
    {
      SerialUSB.println("Success open from string c_str");
    }
}

But this code does work :

SdFile prev,file;
char nextApp[30];

if (file.open("/test/test.bin", O_READ))
{
  SerialUSB.println("Success open");
}

I would really appreciate any help... :slight_smile:
Info :

  • I'm using a custom Arduino Zero board.
  • The NEXTAPP.TXT file contains "/test/test.bin\n"

strcmp returns zero on an exact match and non-zero otherwise.

SerialUSB.println(strcmp(s.c_str(),"/test/test.bin")?"Match":"Differ");

This will print "Match" when the condition is non-zero and therefore when the strings do not match.
Exchange the "Match" and "Differ" strings.

Pete

BTW. You should put i++ inside the if statement so that it doesn't count the '\n'. That way "i" will be the length of the string when the '\n' is found and the while loop exits.

Pete

Thanks for your help, huge mistake with the returned value from strcmp !

Here is the full code :

#include <SdFat.h>

SdFat sd;
SdFile prev, file;

char nextApp[30] = {0};
void setup() {
  // put your setup code here, to run once:
  sd.begin(SD_CS_PIN, SPI_FULL_SPEED);

  while (!SerialUSB);

  if (prev.open("/System/Loader/NEXTAPP.TXT", O_READ))
  {
    char c = 0;
    int i = 0;
    String s = "";
    digitalWrite(13, HIGH);
    memset(nextApp, 0, 30);

    while (c != '\n')
    {
      c = prev.read();
      if (c != '\n')
      {
        s += char(c);
        nextApp[i] = c;
        i++;
      }
    }
    prev.close();


    SerialUSB.println(strcmp(s.c_str(), "/Test/Test.bin") ? "\"/Test/Test.bin\" differs from \"" + String(s.c_str()) + "\"" : "Match");
    SerialUSB.println(strcmp(nextApp, "/Test/Test.bin") ? "Differ" : "Match");

    SerialUSB.print("i = ");
    SerialUSB.println(i);
    SerialUSB.print("s.length() = ");
    SerialUSB.println(s.length());

    if (file.open(nextApp, O_READ))
    {
      SerialUSB.println("File open success using char *");
    }
    else if (file.open(s.c_str(), O_READ))
    {
      SerialUSB.println("File open success using c_str()");
    }
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

Which displays this on the Serial port :

"/Test/Test.bin" differs from "/Test/Test.bin"
Differ
i = 19
s.length() = 19

Oh my god I just figured out : the println function of SdFat add a CRLF, not just a LF at the end of the String... (\r\n). The Arduino Serial port is not displaying the CR, that why when I displayed both Strings, they seemed to be the same.
Issue solved :slight_smile:

I was about to post some code which would show you exactly what was in the string. I suspected a CR or other stray characters.
There's still one thing to clear up. When you print the value of "i", that is not the same "i" as is used to index nextApp when you read the string. That "i" is declared local to the if statement and disappears once the if statement has been executed. You must have declared another "i' further back in the code, probably globally.
That is why it prints 19 instead of 14 (or 15).

Pete

P.S. If a text file on an SD card is created with Windows, it will also have CRLF on the end of the line. When reading text files, it is best to assume that there will be a CR as well as LF at the end of a line and add code to test for CR and ignore it if it is found.

Pete