如何确保在FATFS中重新缠绕目录对象的读取索引?

时间:2019-08-15 14:53:45

标签: c++ embedded fatfs

我猜这是一个基本问题:我在FatFs中使用f_readdir函数从命令行读取目录的内容,但是我无法使该函数多次运行。第一次执行时,它运行良好:我在CLI中键入“ directory”,并且它会在线显示目录中的每个文件。但是,要求它再次重复f_readdir操作(即,在第一个命令成功完成后,再次键入“ directory”命令)不会输出任何内容。

我相信这是因为在f_readdir操作结束时,文件读取对象没有被倒回零,并且随后的读取目录请求从不存在的索引部分开始。至少这是我目前所能看到的最好的解释。它在Elm Chan的FatFs website上说:“当所有目录项都已被读取且没有要读取的项时,会将空字符串存储在fno-> fname []中,而不会出现任何错误。 fno,将倒退目录对象的读取索引。”

这是我的代码。忽略函数参数,它们是RTOS来运行命令:

void Cmd_directory::run(XString param, XRTOS::XCLI::userIO* io){
        DIR dj;         /*[IN] Directory search object */
        FILINFO fno;    /*[OUT] File information structure */
        FRESULT res;

        res = f_opendir(&dj, "0:");

        while (res == FR_OK && fno.fname[0]) {
                res = f_readdir(&dj, &fno);
                io->print((const char*)fno.fname);
                io->print("\r\n");
        }

        f_closedir(&dj);
}

这个while循环是我在网上找到的,因此,不幸的是,我阅读详细的说明后,还没有完全理解fname索引的工作原理。也许它没有意识到它会根据我的while循环的条件到达目录末尾,尽管它当然可以成功完成并关闭目录。当我再次运行该函数时,我可以看到fno对象仍然具有上一次存储的文件信息。

我已经尝试过的东西(在这一点上值得补充,对于编程世界来说我是一个新手):

&fno = nullptr;   //produces "error: lvalue required as left operand of assignment"
FILINFO *p = nullptr;  //produces all sorts of errors
fno = p;
 //these were shots in the dark
fno.fname[0] = 0;      
memset(fno.fname, 0, sizeof(fno.fname));

我认为这是我无法理解的一些基本内容,但是如果我对此不满意,请原谅我。不幸的是,我没有真正的程序员 IRL ,因此我被迫向社区投票。

好的,我使用的是Eclipse IDE和带有STM32L的GNU ARM Build工具。

1 个答案:

答案 0 :(得分:2)

这里:

    while (res == FR_OK && fno.fname[0]) {

fno.fname[0]统一了-您第一次幸运,因为其中包含非零垃圾。它第二次可能包含先前保留在其中的任何功能-即上一次调用中的NUL-立即终止循环。

以下方法应该起作用:

    res = f_readdir( &dj, &fno ) ;
    while( res == FR_OK && fno.fname[0] ) 
    {
        io->print((const char*)fno.fname);
        io->print("\r\n");
        res = f_readdir(&dj, &fno);
    } 

如果没有显式设置循环终止值,则先前的尝试fno.fname[0] = 0;已结束!对您的代码进行以下较小更改也应该起作用:

fno.fname[0] = 1;      
while (res == FR_OK && fno.fname[0]) {
        res = f_readdir(&dj, &fno);
        io->print((const char*)fno.fname);
        io->print("\r\n");
}

,但是如果目录为空,它将打印空白行。

老实说,ELM FatF f_readdir()的语义有些奇怪。您可能会考虑使用包装器来为其提供更一致和常规的界面:

FRESULT readdir( DIR* dp,      /* [IN] Directory object */
                 FILINFO* fno  /* [OUT] File information structure */ )
{
    FRESULT res = f_readdir( dp, fno ) ;
    if( res == FR_OK && fno->fname[0] == 0 ) 
    {
        res = FR_NO_FILE ;
    }

    return res ;
}

然后您可以编写(例如):

while( readdir( &dj, &fno ) == FR_OK )
{
    io->print((const char*)fno.fname);
    io->print("\r\n");
}