You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32如何将SD卡读取的URL转为const char*[]并让指针指向它

问题描述

我需要从ESP32的SD卡中读取电台URL列表,这些URL以带引号的字符串形式存储,每行一个,格式为"http://xxx",(逗号结尾+换行)。目前已通过SD.h将URL存入String url[100];数组,但所用ESP32音频套件要求URL必须通过预定义的const char *urls[]指针数组传入,而非动态读取的String数组。

我尝试用char u[100][255]存储转换后的URL,编写了如下转换代码,但串口打印URL正常,音频却无法播放(直接在代码里初始化const char *urls[]时音频能正常工作):

int readurls(String url[],char u[100][255]){
  File url_list = SD.open("/URLs/URL_LIST.txt");
  String str;
  String a_url;
  int count = 0;
  while (url_list.available() && count < MAX_LINES) {
    str= url_list.readStringUntil('\n');
    //Serial.println(str);
    int delim = str.indexOf(',');
    //a_url=str.substring(0,delim);
    //needed to eliminate the quotes from the strings
    a_url=str.substring(3,delim-1);
    url[count] = a_url;
    // works to this point - that is String Array looks correct 
    a_url+="\0"; // tried to add a null pointer several ways
    //Serial.println(url[count].c_str());
    char ubuf[a_url.length()+1]="";
    a_url.toCharArray(ubuf,a_url.length()+1);
    strncpy(u[count],ubuf,sizeof(u[count]));
    //u[count]=url[count].c_str();
    urls[count]=u[count];
    count++;
  }
  close(url_list);
  return(count);
}
问题排查与修复方案

1. const char *urls[]的常量属性冲突

你定义的urls是const char *类型数组,意味着指针指向的内容不可修改,但代码中直接给urls[count]赋值u[count]会触发未定义行为。解决方案:将urls改为非const的指针数组:

char *urls[100]; // 去掉const,适配动态赋值需求

如果音频套件强制要求const char *,可将u数组定义为全局静态常量,或使用const_cast(仅临时应急,不推荐长期使用)。

2. strncpy未添加空终止符

strncpy不会自动在目标数组末尾添加'\0',若URL长度刚好等于255,u[count]将没有字符串终止符,导致音频套件读取到乱码。解决方案:手动添加终止符:

strncpy(u[count], ubuf, sizeof(u[count]) - 1); // 预留一个位置放终止符
u[count][sizeof(u[count]) - 1] = '\0'; // 强制添加空终止符

3. 文件关闭方式错误

代码中close(url_list)调用错误,SD库的File对象需调用自身成员函数关闭:

url_list.close(); // 替换close(url_list)

4. 字符串解析的鲁棒性问题

原代码用固定下标substring(3, delim-1)截取URL,依赖严格的格式,若SD卡中存在格式异常的行(如空格、引号位置偏移),会导致URL截取错误。解决方案:改用引号位置定位截取,提升兼容性:

int startQuote = str.indexOf('"');
int endQuote = str.indexOf('"', startQuote + 1);
if (startQuote != -1 && endQuote != -1) {
    a_url = str.substring(startQuote + 1, endQuote);
} else {
    continue; // 格式错误,跳过当前行
}

5. 局部数组ubuf的冗余与风险

ubuf是栈上局部数组,存在栈溢出风险,直接用u[count]作为toCharArray的目标更高效安全:

a_url.toCharArray(u[count], sizeof(u[count]));
// 替代原代码中ubuf的中间转换步骤

修复后的完整代码示例

#define MAX_LINES 100
char u[100][255];
char *urls[100]; // 改为非const指针数组

int readurls(String url[]){
  File url_list = SD.open("/URLs/URL_LIST.txt");
  if (!url_list) { // 添加文件打开失败判断
      Serial.println("Failed to open URL_LIST.txt");
      return 0;
  }
  String str;
  String a_url;
  int count = 0;
  while (url_list.available() && count < MAX_LINES) {
    str = url_list.readStringUntil('\n');
    str.trim(); // 去除行首行尾的空格和换行符
    if (str.isEmpty()) { // 跳过空行
        continue;
    }
    // 用引号位置截取URL,更可靠
    int startQuote = str.indexOf('"');
    int endQuote = str.indexOf('"', startQuote + 1);
    if (startQuote == -1 || endQuote == -1) {
        Serial.println("Invalid line format: " + str);
        continue;
    }
    a_url = str.substring(startQuote + 1, endQuote);
    url[count] = a_url;
    // 直接将String转换到u数组
    size_t urlLen = a_url.length();
    if (urlLen >= sizeof(u[count])) {
        Serial.println("URL too long: " + a_url);
        continue;
    }
    a_url.toCharArray(u[count], sizeof(u[count]));
    urls[count] = u[count];
    count++;
  }
  url_list.close();
  return count;
}

内容的提问来源于stack exchange,提问作者waszee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:44:58