原创 深入理解文件系统(四)

2010-3-30 14:20 2767 6 6 分类: MCU/ 嵌入式

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


四、添加命令fcopyfpath


 


1、目的


1fcopy复制功能,原文件保留,新位置建立文件


2fpath在支持相对路径的情况下,显示当前磁盘的当前目录


 


2fcopy命令的实现


1)复制命令的实现思路


首先要打开两个文件,原文件以可读FA_READ的方式打开,新文件以 FA_CREATE_NEWFA_WRITE的方式打开。


然后建立一个循环,每次从原文件读出一个扇区的数据,写入新文件。然后检查原文件 结束标志,已到结尾,则跳出循环。


关闭两个文件,更新文件信息。


2)代码实现


     res = f_open ( &FileOld, (const char *)argv[1], FA_READ );


     res = f_open ( &FileNew, (const char *)argv[2], FA_CREATE_NEW | FA_WRITE );


     for ( ; ; ){


          res = f_read ( &FileOld, (void*)FileBuf, 512, &ByteRead );


             res = f_write ( &FileNew, ( const void *)FileBuf, ByteRead, &ByteWrite );


             if (FileOld.fptr== FileOld.fsize) )break;


       }


      f_close (&FileOld);


      f_close (&FileNew);


编译,下载,功能正确。


 


3fpath命令的实现


1这个命令实现起来稍微有些难度


首先要获取当前磁盘 当前磁盘的当前目录所在簇,也就是FatFs[Drive]->cdir,如果为0,表明是在磁盘根目录,显示0:或者1:。如果该簇号等于根目录所在簇号,当前目录也是在跟目录。


如果不是在根目录,那就要逐层往上搜索了。根据f_opendir (DIR..目录)可以回溯到上层目录,DIR结构体得到了上层目录(X+1)的起始簇号,目录项指针指向第0项。用f_readdir()逐步读出目录项属性,得到FILINFO结构体。如果其簇号 等于 文件系统的当前搜索簇号,则其名称就是所要得到的本层目录名。如果是根目录下则为 0/X目录名


当前搜索簇号设为(X+1)的起始簇号再次调用f_opendir( DIR..目录)此次得到X+2)的起始簇号,判断是否根目录。查找当期搜索簇号在(X+2)目录层中对应的目录项,并获取X+1层的目录名。如果是在根目录,则为0:/X+1目录名/X目录名。


循环直到到达根目录跳出搜索。


 


目录名缓冲区的处理方法。定义总长度为100字节。Path[99]=0;初始化时先让指针指向Path99


得到一个目录,向前移动名称那么长,复制名称。再往前移动1,添加’/’标志。如果是根目录添加’:’,往前移动1,在添加‘驱动号,然后可以显示整个字符串。


 


2代码实现


       for ( ; ; ){


            if ( CurClust == 0 || CurClust == CurFileSys->dirbase ) {


                    PathPtr--;


                    *PathPtr--=':';  /


                    *PathPtr = CurDrive+'0';   //如果当前簇号对应根目录。


                    break;         }


          res = f_opendir ( &DirInf, ".."     ); //第一次执行时,DIR结构体的开始簇号变为X+1层目录的簇号  //第二次时,变为X+2层目录的簇号。


             if ( res!= FR_OK ) break;               


             do {


                    res = f_readdir ( &DirInf, &FileAttrib );


                    TempClust = FileAttrib.sclust;


                    if ( TempClust == CurClust ) break;  //如果该目录项的簇号等于当前搜索簇号,它的名称就是当前需要的目录名


             } while( res == FR_OK );


             if ( res!= FR_OK ) break;


             DirLen= Str_Length ( (const char*)FileAttrib.fname ); //这里要得到字符串的长度。


          PathPtr -= DirLen;  //文件指针往后退目录名长度


             mem_cpy ( (void *)PathPtr, ( const void*)FileAttrib.fname, DirLen);


             PathPtr--;


             *PathPtr='/'; //添加文件间隔/符号。


                             


             CurClust = DirInf.sclust; //当前搜索簇号跟着上移。


       }


       Uart_PutString( PathPtr);  //这是显示的当前目录。


       Uart_PutString( "\r\n");


 


编译,下载,显示两层目录是正确的。但是目录一旦到第三层,就进入死循环。还要接着调试。


 


3调试


经调试发现res = f_opendir ( &DirInf, ".."   )调用后,并不能每次都自动回溯到上一层目录。


所以改为:f_opendir ( &DirInf, (const char*)ddPtr)ddPtr初始化成“..”,然后每循环一次,前面加上”../”第二次变为 ../..”,第三次变为“../../.. “这样目录不断回溯。


以下是该命令实现的截图。


点击看大图 


 


 


 


 


 

文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /2 下一条