前言
这是在学习_finddata_t函数时 attrib属性介绍
//File attribute constants for the _findfirst() family of functions
#define _A_NORMAL 0x00 // Normal file - No read/write restrictions
#define _A_RDONLY 0x01 // Read only file 只读文件
#define _A_HIDDEN 0x02 // Hidden file 隐藏文件
#define _A_SYSTEM 0x04 // System file 系统文件
#define _A_SUBDIR 0x10 // Subdirectory 子目录
#define _A_ARCH 0x20 // Archive file 存档文件
attrib 是一个命令行工具,用于显示文件的属性及其值。
在 Windows 操作系统中,每个文件和目录都有一组属性,属性包括文件名、创建日期、修改日期、文件大小等信息。
这些属性值可以通过 attrib 命令来查看。
下面是常见的 attrib 属性值及其对应的介绍:
A:表示文件或目录被标记为“存档”(Archive)。当文件或目录发生变化时,该标记会被清除。通常用于备份操作。
R:表示文件或目录是只读的(Read-only)。只读属性可以防止用户意外地修改或删除文件或目录。
H:表示文件或目录是隐藏的(Hidden)。隐藏属性可以使文件或目录在文件浏览器中不可见。
S:表示文件或目录是系统文件(System)。系统文件是操作系统需要使用的文件,通常不应该被修改或删除。
I:表示文件或目录是不可索引的(Not content indexed)。不可索引属性可以使文件或目录不出现在 Windows 索引中,从而提高搜索性能。
O:表示文件或目录是脱机的(Offline)。脱机属性可以指示 Windows 在处理网络文件时执行缓存优化,以提高性能。
X:表示文件或目录是加密的(Encrypted)。加密属性可以使文件或目录的内容在存储介质上加密,以保护数据安全。
P:表示文件或目录是稀疏的(Sparse file)。稀疏文件是一种特殊类型的文件,其中大量的空间以零填充,以减少磁盘占用空间。
为什么不用1,2,3,4,5来表示标志位? 如果用顺序数字来表达多种属性,无法组合。为什么呢?
1+2+3 = 6
1+2=3
这个时候就没有办法区分 3代表什么属性?
可能是文件夹,也可能是1+2的属性
所以这边使用的0x00,0x01,0x02,0x04,0x010,0x10,0x20
通过位运算中的与可以来进行判断属于哪一位是表示什么的
示例代码:
#define _CRT_SECURE_NO_WARNINGS
#include<io.h>
#include<stdio.h>
#include<time.h>
int main()
{
_finddata_t fd; // Linux通配符 * Windows下通配符 *.*
intptr_t res = _findfirst("F:\\2023\\0基础C语言\\章节内容\\第一周\\基础运算符号.docx", &fd); //-1代表错误
if (res != -1)
{
struct tm* pt = localtime(&fd.time_write);
printf("修改时间:%d年%d月%d日 %d:%d:%d\n", pt->tm_year + 1900, pt->tm_mon + 1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
printf("%d", fd.size);
//为什么都是2的n的次方 利用标志位 使用位运算 混合判断
if (fd.attrib & _A_RDONLY) //第几位是不是1,如果就是含有这个属性 对混合属性的进行判断
puts("是只读的");
else
puts("不是只读的");
if (fd.attrib & _A_SUBDIR) //第几位是不是1,如果就是含有这个属性 对混合属性的进行判断
puts("是文件夹");
else
puts("不是文件夹");
_findclose(res);
}
}
一、_findnext 函数用法
_findnext是一个函数, 它用于在指定目录中查找下一个与指定的文件名匹配的文件。
函数声明: int _findnext(int hFile, struct _finddata_t *fileinfo);
参数说明:
hFile:是由 _findfirst 函数返回的句柄。
fileinfo:是 _finddata_t 结构类型的指针,它用于存储当前文件的信息。
返回值:
如果函数成功查找到下一个文件,则返回0。
如果函数在查找过程中出错,则返回-1。
函数说明:
_findnext函数通过传入的句柄hFile来查找下一个文件,并将文件信息保存在提供的结构体变量fileinfo中。在第一次使用此函数之前,必须先调用_findfirst函数以获取句柄,因为该句柄将作为后续所有调用的输入参数.
示例代码:
以下是一个简单的示例程序,展示了如何使用_findfirst和_findnext函数来查找指定目录中的所有文件。
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
int main()
{
struct _finddata_t fileinfo;
int iHandle;
// 查找目录下的所有文件
if ((iHandle = _findfirst("C:\\Windows\\*.*", &fileinfo)) == -1)
{
printf("找不到指定的文件\n");
exit(1);
}
else
{
do
{
printf("%s\n", fileinfo.name);
} while (_findnext(iHandle, &fileinfo) == 0);
_findclose(iHandle);
}
return 0;
}
该程序查找Windows目录下的所有文件,并将文件名以字符串形式打印出来。注意,在使用完_findfirst和_findnext函数后,一定要调用 _findclose 函数关闭句柄,以避免资源泄露。
二、对单个目录进行扫描判断
#define _CRT_SECURE_NO_WARNINGS
#include<io.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
/*
#define _A_NORMAL 0x00 // Normal file - No read/write restrictions
#define _A_RDONLY 0x01 // Read only file
#define _A_HIDDEN 0x02 // Hidden file
#define _A_SYSTEM 0x04 // System file
#define _A_SUBDIR 0x10 // Subdirectory
#define _A_ARCH 0x20 // Archive file
*/
int main()
{
_finddata_t fd; //.代表当前目录 ..代表上一层目录 遍历时会过滤掉
intptr_t res = _findfirst("C:\\Users\\ASUS\\Desktop\\*.*", &fd); //-1代表错误 intptr_t 64位返回值是longlong 8个字节来接收
//_findfirst是获取了第一个人的信息
if (res ==-1)
{
puts("没有匹配的结果!");
return -1;
}
do
{
if (strcmp(fd.name, ".") && strcmp(fd.name, ".."))
{
printf("文件名:%s,大小:%d", fd.name, fd.size);
if (fd.attrib & _A_RDONLY)
puts("是只读的");
else
puts("不是只读的");
if (fd.attrib & _A_SUBDIR)
puts("是文件夹");
else
puts("不是文件夹");
struct tm* pt = localtime(&fd.time_write);
printf("修改时间:%d年%d月%d日 %d:%d:%d\n", pt->tm_year + 1900, pt->tm_mon + 1,
pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
}
} while (_findnext(res,&fd)!=-1);
_findclose(res);
return 0;
}
三、 遍历子目录对磁盘下目录扫描
使用递归函数来把所有子目录的内容都打印出来树状遍历必须使用递归)
代码如下(示例):
#define _CRT_SECURE_NO_WARNINGS
#include<io.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
#include<stdlib.h>
static int sum = 0;// 不能放在栈区 放在栈区每个楼层不一样都不知道统计的是谁的
void scan(const char* sPath)
{
_finddata_t fd; // Linux通配符 * Windows下通配符 *.*
char s[_MAX_PATH];
strcpy(s, sPath); //将来源(常量区数据)复制到可变区
strcat(s, "\\*.*");
intptr_t res = _findfirst(s, &fd); //-1代表错误
if (res == -1)
{
puts("没有匹配的结果");
return ;
}
do
{
if (strcmp(fd.name, ".") && strcmp(fd.name, ".."))
{
struct tm* pt = localtime(&fd.time_write);
printf(" %d/%02d/%02d %02d:%02d:%02d ", pt->tm_year + 1900, pt->tm_mon + 1,
pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
if (fd.attrib & _A_SUBDIR) //文件夹
{
printf("%9s%10d %s\n", "<DIR>", fd.size, fd.name);
strcpy(s, sPath);
strcat(s, "\\");
strcat(s, fd.name);
scan(s); //循环遍历子目录 对磁盘下目录扫描
}
else
{
sum++;
printf("%19d %s\n", fd.size, fd.name);
}
}
} while (_findnext(res, &fd) != -1);
_findclose(res);
}
int main()
{
scan("C:\\Users\\ASUS\\Desktop");
printf("总共不包括文件夹的文件个数:%d", sum);
return 0;
}
算法进行优化 将路径放在了全局区
代码如下(示例):
#define _CRT_SECURE_NO_WARNINGS
#include<io.h>
#include<stdio.h>
#include<time.h>
#include<string.h>
#include<stdlib.h>
static int sum = 0;// 不能放在栈区 放在栈区每个楼层不一样都不知道统计的是谁的
char s[_MAX_PATH];
//对disk-scan3优化
void scan(size_t nLen)
{
_finddata_t fd; // Linux通配符 * Windows下通配符 *.*
strcpy(s+nLen, "\\*.*");
intptr_t res = _findfirst(s, &fd); //-1代表错误
if (res == -1)
{
puts("没有匹配的结果");
return;
}
do
{
if (strcmp(fd.name, ".") && strcmp(fd.name, ".."))
{
struct tm* pt = localtime(&fd.time_write);
printf(" %d/%02d/%02d %02d:%02d:%02d ", pt->tm_year + 1900, pt->tm_mon + 1,
pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec);
if (fd.attrib & _A_SUBDIR) //文件夹
{
printf("%9s%10d %s\n", "<DIR>", fd.size, fd.name);
// s[nLen] = '\\';
//s[nLen] =0;
// strcat(s, "\\");
// strcat(s, fd.name); //算法原理从头找到\0 再追加到后面的字符串
strcpy(s + nLen + 1, fd.name);
scan(nLen+1+strlen(fd.name)); //循环遍历子目录 对磁盘下目录扫描
}
else
{
sum++;
printf("%19d %s\n", fd.size, fd.name);
}
}
} while (_findnext(res, &fd) != -1);
_findclose(res);
}
int main()
{
strcpy(s, "C:\\Users\\ASUS\\Desktop");
scan(strlen(s));
printf("总共不包括文件夹的文件个数:%d", sum);
return 0;
}