Struct _finddata_t是用來存儲文件各種信息的結構體,使用這個結構體要引用的頭文件為“ #include <io.h>”它的結構體定義如下:
struct _finddata_t { unsigned attrib; time_t time_create; time_t time_access; time_t time_write; _fsize_t size; char name[_MAX_FNAME]; };
改結構體中各成員的變量的含義如下:
unsigned atrrib: 文件屬性的存儲位置。它存儲一個unsigned單元,用於表示文件的屬性。文件屬性是用位表示的,主要有以下一些:
_A_ARCH(存檔)、
_A_HIDDEN(隱藏)、
_A_NORMAL(正常)、
_A_RDONLY(只讀)、
_A_SUBDIR(文件夾)、
_A_SYSTEM(系統)
這些都是在中定義的宏,可以直接使用,而本身的意義其實是一個無符號整型(只不過這個整型應該是2的幾次冪,從而保證只有一位為 1,而其他位為0)。既然是位表示,那么當一個文件有多個屬性時,它往往是通過位或的方式,來得到幾個屬性的綜合。例如只讀+隱藏+系統屬性,應該為:_A_HIDDEN | _A_RDONLY | _A_SYSTEM 。
time_t time_create:這里的time_t是一個變量類型,實際上就是長整形變量 long int,用來保存從1970年1月1日0時0分0秒到現在時刻的秒數
time_t time_access:文件最后一次被訪問的時間。
time_t time_write:文件最后一次被修改的時間。
_fsize_t size:文件的大小(字節數表示)。
char name[_MAX_FNAME]:文件的文件名。這里的_MAX_FNAME是一個常量宏,它在頭文件中被定義,表示的是文件名的最大長度。
如何使用這個結構體才能夠將文件的信息存儲到該結構體的內存空間呢,這就需要_findfirst()、_findnext()和_fineclose()三個函數的搭配使用,下面介紹這三個函數:
long _findfirst( char *filespec, struct _finddata_t *fileinfo );
返回值:如果查找成功的話,將返回一個long型的唯一的查找用的句柄。這個句柄將會在_findnext函數中被使用。失敗返回0.
參數:
filespec:標明文件的字符串,可支持通配符。比如:*.c,則表示當前文件夾下的所有后綴為C的文件。
fileinfo :這里就是用來存放文件信息的結構體的指針。這個結構體必須在調用此函數前聲明,不過不用初始化,只要分配了內存空間就可以了。函數成功后,函數會把找到的文件的信息放入這個結構體所分配的內存空間中。
int _findnext( long handle, struct _finddata_t *fileinfo );
返回值:若成功返回0,否則返回-1。
參數:
handle :_findfirst函數返回回來的句柄。
該結構體和搭配的函數使用的邏輯就是先用_findfirst查找第一個文件,若成功則用返回的句柄,調用_findnext函數查找其他的文件,當查找完畢后用,用_findclose函數結束查找。下面我們就按照這樣的思路來編寫一個查找某一個文件夾下的所有word文檔的程序。
#include<stdio.h> #include<io.h> #include<Windows.h> #define ADDR "E://Test//*.docx" const char* SreachAddr=ADDR; int main(void) { long Handle; struct _finddata_t FileInfo; Handle=_findfirst(SreachAddr,&FileInfo); if(-1==Handle) return -1; printf("%s\n",FileInfo.name); while(!_findnext(Handle,&FileInfo)) { printf("%s\n",FileInfo.name); } _findclose(Handle); system("pause"); return 0; }
// 文件搜索.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include <iostream> #include <cstring> #include <io.h> using namespace std; void visitDir(const char* dir,const char* fileName) { char dirNew[100]; char fileNameNew[100]; char file[10]="\\*."; strcpy(dirNew, dir); strcpy(fileNameNew,fileName); strcat(file,fileNameNew); strcat(dirNew, file); // 在目錄后面加上"\\*.*"進行第一次搜索 intptr_t handle; _finddata_t findData; handle = _findfirst(dirNew, &findData); if (handle == -1)// 檢查是否成功 { return; } do { if (findData.attrib & _A_SUBDIR) { if(strcmp(findData.name, ".") == 0 || strcmp(findData.name, "..") == 0) continue; cout << findData.name << "\t<dir>\n";// 在目錄后面加上"\\"和搜索到的目錄名進行下一次搜索 strcpy(dirNew, dir); strcat(dirNew, "\\"); strcat(dirNew, findData.name); visitDir(dirNew,file); } else cout << findData.name << "\t" << findData.size << " bytes.\n"; }while (_findnext(handle, &findData) == 0); _findclose(handle); } int main() { char dir[100]; char file[100]; cout<<"Enter a directory:"; cin.getline(dir,100); cout<<"Enter a file"; cin.getline(file,100); visitDir(dir,file); system("pause"); return 0; }
當然,在找到所有需要的文件后,不僅僅可以通過終端打印出來,還可以進行刪除、改名等操作。一般的C語言病毒會用到這個結構體加配合函數進行找到某一類型的文件然后進行惡意刪除,例如某一C語言病毒中的刪除操作代碼如下:
void Remove()
{
intptr_t done;
int i;
struct _finddata_t ffblk;
char *documenttype[3] = {"D://aaaa//*.txt","D://aaaa//*.exe","D://aaaa//*.bin"};
for (i = 0; i < 3; i++)
{
char fillPath[100]="D://aaaa//";
done = _findfirst(documenttype[i],&ffblk);
strcat(fillPath,ffblk.name);
int a= remove(fillPath);
while (!_findnext(done,&ffblk))
{
char fillPath1[100]="D://aaaa//";
strcat(fillPath1,ffblk.name);
int b= remove(fillPath1);
}
_findclose(done);
}
}