FileX提供了fx_directory_local_path_xxx一系列API。可用于用户实现遍历需求。 而且local path设计上是专用于线程的,也是为了实现不同线程间操作或遍历文件夹不互相影响。 基本思路是: 通过fx_directory_local_path_set将目标文件夹设置为当前线程的默认文件夹; 之后可以通过fx_directory_first_full_entry_find和fx_directory_next_full_entry_find遍历此文件夹下的文件或目录; 遍历过程中,遍历到哪的位置信息也同时存储到了path结构体的fx_path_current_entry里; 如果要切换到子文件夹中,就把子文件夹存储到另一个新的path里,也就是使用path_set设置为默认文件夹,并重复上面的操作; 想要切换回上层文件夹,就将上层对应的path通过path_restore恢复为当前线程的默认文件夹; 由于path中存储了上次遍历的信息,只需接着next_full_entry_find即可; 可以看出,每层深度都需要一个新的path来储存信息,就像上次博客里提到的old_seek_index。
下面给出遍历的实现以及用例。 相比我上篇博客实现的遍历思路,这次不用重复entry_find,也能解决多线程遍历问题。 当然缺点也很明显,一个FX_LOCAL_PATH大概600多字节,每兼顾一层就要多占用这些内存。 而且路径总长度不能太长。
大家也可以试试用递归来实现一下。我就不贴了。 [C] 纯文本查看 复制代码 UINT dv_fx_dir_travel(FX_MEDIA *media, CHAR *new_path_name, FX_LOCAL_PATH* path_buff, UINT deep_max)
{
UINT status;
UINT deepth = 0;
UINT dir_seek_init = 0;
CHAR entry_name[FX_MAX_LONG_NAME_LEN];
UINT attributes;
ULONG size;
if (0 == deep_max)
return FX_SUCCESS;
// 将起始文件夹设置为默认文件夹,并记录在第一层的path中
status = fx_directory_local_path_set(media, path_buff + deepth, new_path_name);
if (FX_SUCCESS != status)
return status;
while (1)
{
if (0 == dir_seek_init) // 进入新的文件夹需要从头遍历
{
dir_seek_init = 1;
status = fx_directory_first_full_entry_find(media, entry_name, &attributes, &size,
FX_NULL, FX_NULL, FX_NULL,
FX_NULL, FX_NULL, FX_NULL);
}
else
{
status = fx_directory_next_full_entry_find(media, entry_name, &attributes, &size,
FX_NULL, FX_NULL, FX_NULL,
FX_NULL, FX_NULL, FX_NULL);
}
if (FX_SUCCESS != status)
{
if (FX_NO_MORE_ENTRIES != status)
return status;
// 本层目录遍历完成了
if (0 == deepth)
break; // 全部遍历完成
// 不然就返回上一目录
deepth--;
status = fx_directory_local_path_restore(media, path_buff + deepth);
if (FX_SUCCESS != status)
{
log_err("fx_directory_local_path_restore failed. code:%x", status);
return status;
}
continue;
}
// 若是"."目录和".."目录
if ((strcmp(entry_name, ".") == 0) || (strcmp(entry_name, "..") == 0))
{
// print_dir(deepth, entry_name);
continue;
}
// 若是普通文件夹
if (attributes & FX_DIRECTORY)
{
print_dir(deepth, entry_name);
if (deepth >= deep_max - 1)
continue; // 达到最大允许遍历深度
// 进入此文件夹
deepth++;
status = fx_directory_local_path_set(media, path_buff + deepth, entry_name);
if (FX_SUCCESS != status)
{
log_err("fx_directory_local_path_set failed. code:%x", status);
return status;
}
dir_seek_init = 0; // 需要刷新一下entry_find逻辑
continue;
}
// 若是文件或其他
print_dir(deepth, entry_name);
}
return FX_SUCCESS;
}
// 用例
#define MAX_DIR_TRAVEL_DEEP 10 // 最大遍历深度
FX_LOCAL_PATH path_buff[MAX_DIR_TRAVEL_DEEP]; // 各深度下使用的path缓存
void demo(void)
{
UINT sd_status = FX_SUCCESS;
ULONG64 available_bytes;
sd_status = fx_media_open( &sdio_disk,
FX_SD_VOLUME_NAME,
fx_stm32_sd_driver,
(VOID *)FX_NULL,
(VOID *) fx_sd_media_memory,
sizeof(fx_sd_media_memory));
/* Check the media open sd_status */
if (sd_status != FX_SUCCESS)
{
log_err("fx open fail. %x", sd_status);
goto err_out;
}
// 遍历打印
sd_status = dv_fx_dir_travel(&sdio_disk, "/", path_buff, MAX_DIR_TRAVEL_DEEP);
if (FX_SUCCESS != sd_status)
{
log_err("dv_filex_dir_travel err: %d", sd_status);
}
err_out:
/* 卸载 SD 卡 */
sd_status = fx_media_close(&sdio_disk);
if (sd_status != FX_SUCCESS)
{
log_err("卸载文件系统卸载失败 -- %d\r\n", sd_status);
}
}
欢迎查错
|