SD Card Read into const char * Array works but content is lost

Hi again.

What I am expecting: Reading a txt file on SD Card that contains URL's for Internet radio that can be used in a program.

The Issue: Reading in data from a text file to an array ( const char*URL PROGMEM ={"","",""} as a global array ) Array works, printing out the text file to Serial Monitor also works within the While(file.available) loop, the trouble comes when accessing the URL[Current_URL] data previously stored in this URL, the data is gone


```cpp
#include "SD.h"
#include "FS.h"
#include <SPI.h>

#define HSPI_SS 5
// SD Card
#define TFT_SD_CS     5 
#define TFT_SD_SCK    18
#define TFT_SD_MISO   19
#define TFT_SD_MOSI   23

int Current_URL = 0;
int Max_Current_URL = 5; // Number of URL's in array - 1

bool SD_State_Status = false;

const char *URL[] PROGMEM =  {"","","","","","","","","",""};

SPIClass *hspi = NULL;
File root;
File file;
/* ************************************************************************* */
/* * Function Name:- SD_Init()                                             * */
/* * Description:-   Creates a new SPI Class for use with the built in     * */
/* * SD Card reader/writer tests what card it is and initialises the card  * */
/* * for use with this program                                             * */
/* *                                                                       * */
/* ************************************************************************* */
void SD_Init() {

  hspi = new SPIClass(HSPI);
  hspi->begin(TFT_SD_SCK, TFT_SD_MISO, TFT_SD_MOSI, TFT_SD_CS);

  if (!SD.begin(TFT_SD_CS, *hspi)) {
    Serial.printf("Card Mount Failed\n");
    SD_State_Status = false;
    return;
  } else {
    Serial.printf("Card mounted successfully....\n");
  }
  uint8_t cardType = SD.cardType();
  if (cardType == CARD_NONE) {

    Serial.println("No SD card attached");
    SD_State_Status = false;
    return;
  }

  Serial.printf("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.printf("MMC\n\n");
  } else if (cardType == CARD_SD) {
    Serial.printf("SDSC\n\n");
  } else if (cardType == CARD_SDHC) {
    Serial.printf("SDHC\n\n");
  } else {
    Serial.printf("UNKNOWN\n\n");
  }
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluGB\n\n", cardSize / 1000);
  SD_State_Status = true;
  delay(4000);
  return;`
}
/* ************************************************************************* */
/* * Reads back the URLs from Station_List.cfg and stores them in an Array * */
/* * called URL[] each line of text is a URL and is stored                 * */
/* ************************************************************************* */
void Read_Config_File_Station_List() {
  long Seek_Pos = 0;
  char *URL_Tmp[200] = {""};
  Max_Current_URL = 0;
  file = SD.open("/Station_List.cfg", FILE_READ);
  if (!file) Serial.println("Unable to open file");
  do  {
    Serial.println("Unable to open file");
  } while (!file);
  Serial.println("File Opened");
  String temp_Str;
  while (file.available() > 0)  {
    file.seek(Seek_Pos);
    delay(100);
    temp_Str = file.readStringUntil('\r');
    delay(100);
    temp_Str.trim();
    URL[Current_URL] = temp_Str.c_str();
    delay(100);
    Serial.printf("URL[%d]:- %s | This Station Position Within File:- %d\n", Current_URL, URL[Current_URL], Seek_Pos);
    Seek_Pos += temp_Str.length() + 2, Max_Current_URL ++, Current_URL ++;
  }
  file.flush();
  Max_Current_URL --;
  int Station_Count = Max_Current_URL;
  Serial.println("File Closed");
  Serial.printf("Max_Current_URL:- %d | Station_Count:- %d\n", Max_Current_URL, Station_Count);
  for ( int c = 0 ; c <= Station_Count ; c  ++ ) {
    Serial.printf("URL[%d]:- %s\n", c, URL[c]);
  }
  file.close();
}

/* ******************************************************** */
/* *Creates a list on SD called Station_List.cfg and fills this file with      */
/* *Internet Radio URLs                                                                              * */

void Create_Station_Config_File() {
  root = SD.open("/");
  file = SD.open("/Station_List.cfg", FILE_WRITE);
  if (!file) Serial.println("Unable to open file");
  do  {
    Serial.println("Unable to open file");

  } while (!file);
  Serial.println("File Opened");
  for ( int c = 0; c <= Max_Current_URL; c ++)  {
    file.println(URL[c]);
  }
  file.flush();
  file.close();
}

void setup()	{
	int Station_Count = 0;
  Serial.begin(115200);
  delay(1000);
	SD_Init();
//  Create_Station_Config_File(); // Creates a config file for this program
  Read_Config_File_Station_List();  // Opens and extracts Station URL's for use in this program.
  for ( int c = 0 ; c <= Station_Count ; c  ++ ) {
    Serial.printf("URL[%d]:- %s\n", c, URL[c]);
  }
}

void loop()	{

}

The output from this code snippet is the following:-
SD Card Size: 1GB

Unable to open file
File Opened
URL[0]:- http://edge-bauerall-01-gos2.sharp-stream.com/absoluteradio.mp3?aw_0_1st.skey=1748828163&aw_0_1st.playerid=BMUK_RPi 

 URL[1]:- http://edge-bauerall-01-gos2.sharp-stream.com/absoluteclassicrockhigh.aac?aw_0_1st.skey=1748993576&aw_0_1st.playerid=BMUK_RPi

URL[2]:- http://edge-bauerall-01-gos2.sharp-stream.com/net2southwales.mp3?aw_0_1st.skey=1748828453

URL[3]:- http://edge-bauerall-01-gos2.sharp-stream.com/magicnational.mp3?aw_0_1st.skey=1748828719

URL[4]:- http://listen-nation.sharp-stream.com/nationwest.mp3?ref=RF | This Station Position Within File:- 425

16:15:55.478 -> URL[5]:- | This Station Position Within File:- 486
16:15:55.478 -> File Closed
16:15:55.478 -> Max_Current_URL:- 5 | Station_Count:- 5
16:15:55.478 -> URL[0]:-
16:15:55.478 -> URL[1]:-
16:15:55.478 -> URL[2]:-
16:15:55.478 -> URL[3]:-
16:15:55.478 -> URL[4]:-
16:15:55.478 -> URL[5]:-
16:15:55.519 -> URL[0]:-

The first 5 URL's Above (Following the File Opened Statement) is the initial point at which the data is retrieved, as you can see this works as expected, the 2nd block of Data following the File Closed statement is the for loop at the foot of the Read_Config_File_Station_List() function. The function Create_Station_Config_File() creates the config file (obviously), the Station_List.cfg file contains the listed URLs, one to a line with a \r and \n following them.

Does anyone know why this data is being lost? or have a solution to remedy it, I have also tried padding the Array with '0' ( character 0) up to the size of the Array elements (URL[10][200])
Thanks in advance an apologies if I've messed up the post formatting.

PROGMEM uses flash memory rather than SRAM.

You can't write to flash memory like you can to SRAM.

Edit: I see this is likely an ESP32 rather than an Uno. So PROGMEM doesn't really do anything. const on the other hand, likely still does the same thing. Surprised the compiler didn't throw an error on compile.

Thank you, just made few changes in the readStringUntil() i changed the '\r' to '\n' now the last URL is being printed in all the URL Elements this was after removing the PROGMEM directive,

Device is a ESP32-2832S028R 2.8" TFT Display (aka Cheap Yellow Display)

This will create an array of constant pointers to char (or pointers to string), but not the string itself.

Further in the code you put a pointer to you temporary string to the elements of URL array.

Doing so, you are making two serious mistakes:

  • you save in URL[] array a pointer to temporary object. The string temp_Str is local for Read_Config_File_Station_List() function. It will be destroyed after the code leave the function and all its contents will be lost.
  • the second mistake is that you copy the same pointer (temp_Str.c_str()) to the all elements of URL array

nothing surprising

read the last sentence of my post #4

As I see, you don't quite understand a pointers and arrays.

The line below again is an array of pointers to char rather than array of chars:

Sorry, but your whole code contains a lot of such bugs.

No that's fine, the Last time I used C was over 25 year ago, only come back to it a few months ago. so basically a little knowledge is dangerous. and no my understanding of Arrays and Pointer are extremely limited in scope.

How would I write this code to get to the data it holds? or how do I write the code block to retrieve and store the data from the SD Card file to the URL[] Array.

I am stuck on this issue tried numerous ways to sort this out including rewriting using various methods but nothing works.

Thanks