硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1351|回复: 1
收起左侧

[FileX] 使用FileX提供的基础API实现遍历

[复制链接]

10

主题

75

回帖

120

积分

初级会员

积分
120
发表于 2024-7-1 22:49:25 | 显示全部楼层 |阅读模式
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);
    }
}

欢迎查错


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2024-7-2 09:10:42 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-13 04:20 , Processed in 0.058317 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表