如何确保在 FATFS 中倒带目录对象的读取索引?



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

我相信这是因为文件读取对象在操作结束时没有倒带到零f_readdir并且随后读取目录的请求从不存在的索引部分开始。至少,这是我目前能看到的最好的解释。它在Elm Chan的FatFs网站上说:"当所有目录项目都被读取并且没有要读取的项目时,一个空字符串被存储到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("rn");
}
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,所以我被迫对社区进行民意调查。

哦,对了,我正在使用带有STM32L的Eclipse IDE,GNU ARM构建工具。

在这里:

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("rn");
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("rn");
}

但如果目录为空,它将打印一个空行。

老实说,ELM FatFsf_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("rn");
}

最新更新