Filesystems SdFat库ls()上显示大量隐藏文件
我的目标是能够浏览SD卡上的文件系统,选择特定的文件类型并向用户显示它们。当我在SdFat库上执行Filesystems SdFat库ls()上显示大量隐藏文件,filesystems,arduino,sd-card,hidden-files,Filesystems,Arduino,Sd Card,Hidden Files,我的目标是能够浏览SD卡上的文件系统,选择特定的文件类型并向用户显示它们。当我在SdFat库上执行sd.ls(ls\u R)时,它会显示许多隐藏的文件。我能很好地处理大多数问题,但有些问题让我头疼。由于库使用8.3命名约定,它会截断过长的文件/文件夹名称,并将其替换为“~”。这是一个问题,因为我无法区分可见的文件/文件夹和隐藏的文件/文件夹。有什么已知的方法可以解决这个问题吗 这是我的密码: #include <SdFat.h> const uint8_t chipSelect =
sd.ls(ls\u R)
时,它会显示许多隐藏的文件。我能很好地处理大多数问题,但有些问题让我头疼。由于库使用8.3命名约定,它会截断过长的文件/文件夹名称,并将其替换为“~”。这是一个问题,因为我无法区分可见的文件/文件夹和隐藏的文件/文件夹。有什么已知的方法可以解决这个问题吗
这是我的密码:
#include <SdFat.h>
const uint8_t chipSelect = 10;
SdFat sd;
SdFile file;
void setup()
{
Serial.begin(9600);
while (!Serial) {} // wait for Leonardo
delay(1000);
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
sd.ls(LS_R);
while(1);
}
void loop() {}
以下是输出:
FOLDER1/
TEST4.TXT
TEST3.TXT
TEST2.TXT
~1.TRA
TEST1.TXT
TRASHE~1/
SPOTLI~1/
STORE-V2/
F8D581~1/
PSID.DB
TM~1.SNO
TM~1.LIO
LIO~1.CRE
TMP.CAB
CA~1.CRE
INDEXS~1
~1.IND
~~2.IND
~~~3.IND
~~~~4.IND
~~~~~5.IND
~~~~~~34.IND
~~~~~~37.IND
~~~~~~40.IND
~~~~~~43.IND
~~~~~~46.IND
~~~~~~48.IND
~1.DIR
LIVE~~~4.IND
LIVE~~2.IND
LIVE~~~3.IND
LIVE~~~5.IND
LIVE~~66.IND
LIVE~~69.IND
LIVE~~73.IND
LIVE~1.SHA
LIVE~~79.IND
LIVE~1.DIR
LIVE0D~1.SHA
STORE.DB
STOR~1.DB
REVERS~1
TMPSPO~1.STA
PERMST~1
STORE_~1
JOURNA~1.LIV/
JOURNA~2.LIV/
RETIRE.3
JOURNA~3.LIV/
RETIRE.4
JOURNA~4.LIV/
JOURNA~1.ASS/
JOURNA~2.ASS/
JOURNA~1.HEA/
JOURNA~1.MIG/
JOURNA~2.MIG/
JOURNA~1
JOURNA~1.SCA/
RETIRE.11
REVERS~1.SHA
~1.SHA
SHUTDO~1
JOURNA~1.REP/
CA~1.MOD
LIVE~155.IND
LIVE~158.IND
0DIREC~1.SHA
~~~~~166.SHA
LIVE~169.IND
LIVE~172.IND
LIVE~175.IND
LIVE~178.IND
LIVE~181.IND
LIVE~184.IND
LIVE~1.IND
LIVE~190.IND
LIVE~194.SHA
STOR~1.UPD
REVERS~1.UPD
LIVE~202.IND
TMPSPO~1.LOC
LIVE~208.IND
LIVE~211.IND
LIVE~215.IND
LIVE~218.SHA
LIVE~~2.DIR
LIVE1D~1.SHA
LIVE~264.SHA
LIVE~267.IND
LIVE~270.IND
LIVE~274.IND
LIVE~277.IND
LIVE~~~3.DIR
LIVE~~2.SHA
LIVE~~~3.SHA
LIVE~~~4.SHA
LIVE~~~5.SHA
LIVE~296.SHA
LIVE~300.SHA
LIVE2D~1.SHA
LIVE~308.SHA
LIVE~327.IND
STORE-V1/
VOLUME~1.PLI
VOLUME~1.PLI
FOLDER2/
BEARSO~1/
LONGFI~1.TXT
因此,我的问题是,如何区分未隐藏的
BEARSO~1/
[BearsOutside]和隐藏的SPOTLI~1/
?不幸的是,一些基本函数不能直接用于
SdFat sd;
反对。因此,排除了“ls”函数的使用。下面的代码应该可以实现您想要的功能。它将sd objects当前文件传递给指针p的目录条目对象。然后可以对其属性进行测试,看看它们是隐藏的还是其他的
注意,有一种方法可以测试目录条目是否为长名称。但是,我不相信该条目正在缓存长名称本身
下面的代码确实可以编译。其中99.5%来自我使用的工作代码。我已经添加了属性和长文件名检测,所以它应该可以工作
void ListFiles2(uint8_t flags) {
// This code is just copied from SdFile.cpp in the SDFat library
// and tweaked to print to the serial output in html!
dir_t p;
sd.vwd()->rewind();
Serial.println();
while (sd.vwd()->readDir(&p) > 0) {
// done if past last used entry
if (p.name[0] == DIR_NAME_FREE) break;
// skip deleted entry and entries for . and ..
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;
// only list subdirectories and files
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
if ((p.attributes & DIR_ATT_HIDDEN) != DIR_ATT_HIDDEN) continue;
// print any indent spaces
Serial.print(F(" "));
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
Serial.print('.');
}
Serial.print((char)p.name[i]);
}
Serial.print(F(" "));
// print file name with possible blank fill
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
Serial.print('.');
}
Serial.print((char)p.name[i]);
if (DIR_IS_LONG_NAME(&p)) {
Serial.print(F(" long fn"));
}
}
if (DIR_IS_SUBDIR(&p)) {
Serial.print('/');
}
// print modify date/time if requested
if (flags & LS_DATE) {
sd.vwd()->printFatDate(p.lastWriteDate);
Serial.print(' ');
sd.vwd()->printFatTime(p.lastWriteTime);
}
// print size if requested
if (!DIR_IS_SUBDIR(&p) && (flags & LS_SIZE)) {
Serial.print(' ');
Serial.print(p.fileSize);
}
Serial.println();
}
Serial.println();
}
void ListFiles2(uint8\t标志){
//此代码只是从SDFat库中的SdFile.cpp复制的
//并调整为以html格式打印到串行输出!
董事会;
sd.vwd()->倒带();
Serial.println();
而(sd.vwd()->readDir(&p)>0){
//如果超过上次使用的条目,则完成
如果(p.name[0]==DIR\u name\u FREE)中断;
//跳过删除的条目以及.和..的条目。。
如果(p.name[0]==DIR|u name|u DELETED | p.name[0]='.')继续;
//仅列出子目录和文件
如果(!DIR_是文件或子文件(&p))继续;
如果((p.attributes&DIR\u ATT\u HIDDEN)!=DIR\u ATT\u HIDDEN)继续;
//打印任何缩进空格
连续打印(F(“”);
对于(uint8_t i=0;i<11;i++){
如果(p.name[i]='')继续;
如果(i==8){
序列号。打印('.');
}
串行打印((字符)p.name[i]);
}
连续打印(F(“”);
//打印文件名,可能填写空白
对于(uint8_t i=0;i<11;i++){
如果(p.name[i]='')继续;
如果(i==8){
序列号。打印('.');
}
串行打印((字符)p.name[i]);
如果(目录为长名称(&p)){
连续打印(F(“长fn”);
}
}
if(DIR_IS_SUBDIR&p)){
序列号。打印(“/”);
}
//如果需要,打印修改日期/时间
如果(标志和标记日期){
sd.vwd()->printFatDate(p.lastWriteDate);
序列号。打印(“”);
sd.vwd()->printFatTime(p.lastWriteTime);
}
//如有要求,请打印尺寸
如果(!DIR_IS_subdr(&p)和&(flags&LS_SIZE)){
序列号。打印(“”);
Serial.print(p.fileSize);
}
Serial.println();
}
Serial.println();
}
这些文件由Mac OSX系统自动创建。。。您是否可以选择不在任何Mac电脑上插入SD卡?这会解决你的问题…;-)
您也可以尝试在Mac上使用终端删除它们。这是一个非常古老的问题,但它在google搜索中出现得很高,因此我将提供一些更新信息: 截至撰写本文之时(2020年秋季),SdFat已进行了重大升级。SdFat-2.0已经面世好几年了,尽管它仍然被标记为beta.8(自述文件中称为“早期beta”),但已知问题相对较少,并且在许多网站上投入生产使用 起初我对采用它犹豫不决,但它提供了如此急需的新功能,最终我咬紧牙关接受了它。事实证明,它非常容易集成,而且非常稳定 SdFat-2.0包括对ExFat卷、长文件名和文件集群预分配的强大支持,并提供了一种机制来保证对SD卡的非阻塞写入。这解决了长期存在的偶尔阻塞长写入延迟的问题,该延迟通常会干扰SD卡上的数据记录。对于ExFat卷,将自动处理预分配文件空间最终截断的数据大小计算 SdFat-2.0支持多个卡,即使它们运行在不同的总线或不同的总线类型上。我有一个带有三个SD卡的设备,一个由SDIO寻址,两个运行在不同的SPI总线上,我可以毫不费力地复制文件 另外,与旧的arduino库只有两个不兼容之处,许多其他库依赖于此: SDFat-2.0为
begin()
使用新语法,传递一个配置对象,告诉您的SD卡是如何连接的以及应该如何寻址
SdFat-2.0不支持较旧的file.name()
函数,因为它是为8.3文件名设置的。相反,通过传递一个常量char*来获得长文件名,该常量char*指向文件名可以存储的地方。您需要完整的文件名才能打开文件,但是如果您可以坚持使用8.3文件名,那么您可以创建一个包装器,该包装器实现一个简单的无参数begin()
以及旧的name()
函数。这将使所有内容与sd.h
完全兼容,并避免对库进行任何#ifdef
修补
这是我发现的唯一的兼容性问题,我个人没有遇到任何bug。您可以在此处找到github项目:
void ListFiles2(uint8_t flags) {
// This code is just copied from SdFile.cpp in the SDFat library
// and tweaked to print to the serial output in html!
dir_t p;
sd.vwd()->rewind();
Serial.println();
while (sd.vwd()->readDir(&p) > 0) {
// done if past last used entry
if (p.name[0] == DIR_NAME_FREE) break;
// skip deleted entry and entries for . and ..
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;
// only list subdirectories and files
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
if ((p.attributes & DIR_ATT_HIDDEN) != DIR_ATT_HIDDEN) continue;
// print any indent spaces
Serial.print(F(" "));
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
Serial.print('.');
}
Serial.print((char)p.name[i]);
}
Serial.print(F(" "));
// print file name with possible blank fill
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
Serial.print('.');
}
Serial.print((char)p.name[i]);
if (DIR_IS_LONG_NAME(&p)) {
Serial.print(F(" long fn"));
}
}
if (DIR_IS_SUBDIR(&p)) {
Serial.print('/');
}
// print modify date/time if requested
if (flags & LS_DATE) {
sd.vwd()->printFatDate(p.lastWriteDate);
Serial.print(' ');
sd.vwd()->printFatTime(p.lastWriteTime);
}
// print size if requested
if (!DIR_IS_SUBDIR(&p) && (flags & LS_SIZE)) {
Serial.print(' ');
Serial.print(p.fileSize);
}
Serial.println();
}
Serial.println();
}