发帖
1 0 0

在小安派bw21中实现sd卡的滚动存储

xiaojin
注册会员

0

主题

1

回帖

58

积分

注册会员

积分
58
小安派Cam 47 1 2025-6-6 16:29:40
本帖最后由 xiaojin 于 2025-6-9 09:15 编辑

在小安派bw21中实现sd卡的滚动存储
  1. // 生成文件夹名时间戳 (格式: YYYY-MM-DD)
  2. String generateDirName(time_t time)
  3. {
  4.     char fileName[11]; // YYYY-MM-DD + null
  5.     snprintf(fileName, sizeof(fileName), "%04d-%02d-%02d",
  6.             year(),month(),day());
  7.     return String(fileName);
  8. }
  9. // 生成文件名时间戳 (格式: hhmmss)
  10. String generatefileName(time_t time)
  11. {
  12.     char fileName[7]; // hhmmss + null
  13.     snprintf(fileName, sizeof(fileName), "%02d%02d%02d",
  14.             hour(),minute(),second());
  15.     return String(fileName);
  16. }
  17. // 从文件夹名解析时间戳 (格式: YYYY-MM-DD)
  18. uint32_t parseFolderTimestamp(const char *folderName)
  19. {
  20.   // 快速验证长度和基本格式
  21.   if (strlen(folderName) < 10 || folderName[4] != '-' || folderName[7] != '-') {
  22.     return 0;
  23.   }

  24.   // 直接验证所有数字位,避免内存拷贝
  25.   for (uint8_t pos : {0, 1, 2, 3, 5, 6, 8, 9}) {
  26.     if (!isdigit(folderName[pos])) {
  27. #ifdef DEBUG
  28.       Serial.print("Invalid char in: ");
  29.       Serial.println(folderName);
  30. #endif
  31.       return 0;
  32.     }
  33.   }

  34.   // 直接计算时间戳值(避免字符串操作)
  35.   return (folderName[0] - '0') * 10000000 +  // 年 - 亿位
  36.          (folderName[1] - '0') * 1000000 +   // 年 - 百万位
  37.          (folderName[2] - '0') * 100000 +    // 年 - 十万位
  38.          (folderName[3] - '0') * 10000 +     // 年 - 万位
  39.          (folderName[5] - '0') * 1000 +      // 月 - 千位
  40.          (folderName[6] - '0') * 100 +       // 月 - 百位
  41.          (folderName[8] - '0') * 10 +        // 日 - 十位
  42.          (folderName[9] - '0');              // 日 - 个位
  43. }
  44. // 删除最旧的文件夹
  45. void deleteOldestFolder()
  46. {
  47.   char resultBuf[MAX_DIR_NAME_LEN];
  48.   char * p;
  49.   char oldestFolder[32] = {0};  // 使用固定缓冲区
  50.   uint32_t oldestTimestamp = UINT32_MAX;  // 初始化为最大时间值
  51.   bool found = false;
  52. #ifdef DEBUG  
  53.   Serial.println("开始查找最旧文件夹...");
  54. #endif  
  55.   memset(resultBuf,0,sizeof(resultBuf));   
  56.   // 重置目录遍历
  57.   int dirResult = fs.readDir(fs.getRootPath(), resultBuf, sizeof(resultBuf));
  58.   
  59.   if (dirResult != 0)
  60.   {
  61.     Serial.println("错误: 无法读取根目录");
  62.     return;
  63.   }
  64.   p = resultBuf;
  65.   while (strlen(p) > 0)
  66.   {
  67. #ifdef DEBUG
  68.       printf("%s\r\n", p);
  69. #endif
  70.       // 尝试解析文件夹名中的时间戳 (格式: YYYY-MM-DD)
  71.       uint32_t folderTimestamp = parseFolderTimestamp(p);
  72.       
  73.       if (folderTimestamp == 0)
  74.       {
  75.         Serial.println("警告: 文件夹名格式错误,跳过");
  76.         //读取下一个文件夹
  77.          p += strlen(p) + 1;
  78.         continue;
  79.       }
  80. #ifdef DEBUG      
  81.       Serial.print("文件夹时间戳: ");
  82.       Serial.println(folderTimestamp);
  83. #endif      
  84.       // 比较并记录最旧文件夹
  85.       if (folderTimestamp < oldestTimestamp)
  86.       {
  87.         oldestTimestamp = folderTimestamp;
  88.         strncpy(oldestFolder, p, strlen(p) - 1);        //copy最旧的文件夹
  89.         oldestFolder[sizeof(oldestFolder) - 1] = '\0';  // 确保终止
  90.         found = true;
  91. #ifdef DEBUG
  92.         Serial.print("更新最旧文件夹为: ");
  93.         Serial.println(oldestFolder);
  94. #endif
  95.       }
  96.       //读取下一个文件夹
  97.       p += strlen(p) + 1;
  98.   }
  99.   
  100.   // 检查是否找到最旧文件夹
  101.   if (found)
  102.   {
  103. #ifdef DEBUG
  104.     Serial.print("确定删除最旧文件夹: ");
  105.     Serial.println(oldestFolder);
  106. #endif
  107.     // 递归删除目录内容
  108.     deleteRecursive(oldestFolder);
  109.   }
  110.   else
  111.   {
  112.     Serial.println("警告: 未找到符合条件的文件夹");
  113.   }
  114. }

  115. // 递归删除目录及其内容
  116. void deleteRecursive(const char *path)
  117. {
  118. #ifdef DEBUG
  119.   Serial.print("开始删除: ");
  120.   Serial.println(path);
  121. #endif

  122.   const int BUF_SIZE = 256; // 足够大的路径缓冲区
  123.   char resultBuf[1584];        // 目录条目缓冲区
  124.   char fullPath[BUF_SIZE];     // 完整路径缓冲区
  125.   
  126.   // 打开目标目录
  127.   int dirResult = fs.readDir((char*)path, resultBuf, sizeof(resultBuf));
  128.   
  129.   if (dirResult != 0) {
  130.     Serial.println("错误: 无法打开目录");
  131.     return;
  132.   }

  133.   char *p = resultBuf;
  134.   // 处理目录中的所有条目
  135.   while (strlen(p) > 0)
  136.   {
  137.       // 跳过当前目录和上级目录
  138.       if (strcmp(p, ".") == 0 || strcmp(p, "..") == 0) {
  139.         p += strlen(p) + 1;
  140.         continue;
  141.       }
  142.       
  143.       // 安全构建完整路径
  144.       int pathLen = snprintf(fullPath, BUF_SIZE, "%s/%s", path, p);
  145.       
  146.       // 检查路径长度是否溢出
  147.       if (pathLen >= BUF_SIZE || pathLen < 0) {
  148.         Serial.print("路径过长,跳过: ");
  149.         Serial.println(p);
  150.         p += strlen(p) + 1;
  151.         continue;
  152.       }
  153. #ifdef DEBUG
  154.       Serial.print("处理: ");
  155.       Serial.println(fullPath);
  156. #endif      
  157.       // 判断是否为目录
  158.       if (fs.isDir(fullPath)) {
  159.         // 递归删除子目录
  160.         deleteRecursive(fullPath);
  161.       } else {
  162.         // 删除文件
  163.         if (fs.remove(fullPath)) {
  164.           Serial.println("文件删除成功");
  165.         } else {
  166.           Serial.println("文件删除失败");
  167.         }
  168.       }
  169.       
  170.       // 读取下一个条目
  171.       p += strlen(p) + 1;
  172.   }
  173. #ifdef DEBUG  
  174.   // 删除当前空目录
  175.   Serial.print("删除空目录: ");
  176.   Serial.println(path);
  177. #endif
  178.   if (fs.rmdir(path)) {
  179.     Serial.println("目录删除成功");
  180.   } else {
  181.     Serial.println("目录删除失败");
  182.   }
  183. }
复制代码
──── 0人觉得很赞 ────

使用道具 举报

学习
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28987 个
  • 话题数: 41749 篇