everything原理解釋與簡單實現。

2021-10-02 17:43:11 字數 4025 閱讀 2264

外面疫情正嚴重,老師也還沒開始上課,我都在家宅了乙個多月了。。。實在是閒的無聊。學習?怎麼可能,學習是不可能學習的,這輩子都不可能學習的。

前幾天,在和大佬聊天的時候,偶然聽說了乙個名叫everything的軟體,可以很方便的查詢電腦內的檔案位置,據說可以秒出結果。只不過只針對ntfs檔案系統的盤。在網上查了下,才知道是依賴於ntfs系統自身的特性。everything使用了ntfs檔案系統自身的usn journal。這個usn是什麼東西呢,它就相當於ntfs的乙個秘書,對ntfs裡任何乙個檔案的操作都會被如實的記錄下來。在ntfs分區內,檔案資訊儲存在mft內,mft表裡的記錄包含了檔案和目錄的所有資訊,例如檔名/目錄名、路徑、大小、屬性等。此外,還會儲存該檔案/目錄最後一次變化所對應的usn,系統在更新usn journal時,也會更新這個字段。

everything在第一次啟動時,會獲取mft內的所有記錄,將其儲存在資料庫內,以後每次啟動時只要獲取一下usn journal的檔案更新資訊就好了。所以查詢時是查的資料庫內的資料而非直接在電腦內查,速度自然快得多。

實現思路,首先利用getlogicaldrivestrings函式獲取電腦內所有的系統碟符,然後利用getvolumeinformationa函式判斷是否是ntfs檔案系統,如果是,使用createfilea函式獲取系統盤控制代碼,然後使用deviceiocontrol函式,使用fsctl_create_usn_journal引數初始化usn檔案,再使用fsctl_query_usn_journal引數獲取資訊,接下來使用fsctl_enum_usn_data引數獲取系統的所有的檔案資訊,由於mft表內沒有記錄檔案的路徑,只有檔案號(filereferencenumber)和父檔案號(parentfilereferencenumber),而windows自身沒有提供相應的api來完成這個功能,所以這部分只能自己實現。在獲取了所有檔案資訊後,可以使用fsctl_read_usn_journal引數監控系統中的檔案變化,最後記得刪除usn檔案。

#include #include #include #include #include #include #include #include #include using namespace std;

#define ll long long

#define buf_len 4096//4k

struct node

;mysql mysql;//mysql連線

mysql_res *res;//返回行的乙個查詢結果集

mysql_row rows;//乙個行資料的型別安全(type-safe)的表示

string sql;//sql 語句

char buf[buf_len];//緩衝區,大小為4k

handle handle;//驅動盤控制代碼

const ll trueroot=1407374883553285;//根目錄的檔案號,似乎所有的ntfs檔案系統的根檔案號都是這個,與盤無關,甚至與機器無關

int num=0;//檔案個數

map> >ma;//因為乙個目錄內不一定只有乙個子目錄或檔案,所以是1對多對映

mapmm;//

vectorve;

void getusnupdate(usn_journal_data ujd)//理論上方法應該沒問題,但獲取的東西根本不是我想要的,所以這個函式似乎沒用

; for(; deviceiocontrol(handle,fsctl_read_usn_journal,&rujd,sizeof(rujd),buf,buf_len,&usndatasize,null); \

rujd.startusn=*(usn*)&buf)

; widechartomultibyte(cp_acp,null,usnrecord->filename,len/2,filename,len,null,null);

ve.push_back();

dword recordlen = usnrecord->recordlength;

len -= recordlen;

usnrecord=(pusn_record)((pchar)usnrecord+recordlen); //獲取下乙個usn記錄

} }}void closeusn(usn_journal_data &ujd,dword &br)//關閉usn journal資料檔案

; deviceiocontrol(handle,fsctl_delete_usn_journal,&dujd,sizeof(dujd),null,0,&br,null);

}void getusndata(usn_journal_data &ujd)//獲取usn journal資料

; for(; deviceiocontrol(handle,fsctl_enum_usn_data,&med,sizeof(med),buf,buf_len,&usndatasize,null); \

; widechartomultibyte(cp_acp,null,usnrecord->filename,len/2,filename,len,null,null);

ma[usnrecord->parentfilereferencenumber].push_back(make_pair(usnrecord->filereferencenumber,filename));//儲存資訊

dword recordlen = usnrecord->recordlength;

len -= recordlen;

usnrecord=(pusn_record)((pchar)usnrecord+recordlen); //獲取下乙個usn記錄

} }}void getusnloginformation(dword &br)

else printf("獲取usn journal資訊失敗%d\n",getlasterror());

}void initusnlog()

; if(deviceiocontrol(handle,fsctl_create_usn_journal,&cujd,sizeof(cujd),null,0,&br,null))

getusnloginformation(br);

else printf("初始化usn journal檔案失敗,%d\n",getlasterror());

}void gethandle(char *name)//獲取驅動盤控制代碼

bool checkntfs(char* name)//檢查是否是ntfs檔案系統盤

void replace(string &str)

}void build(string path,string name,long long pfrn)//採用dfs進行建樹,路徑,檔名和父檔案號

else

// }

// else

//

// }

}void dfsfindfile(string path,string name,regex r)//自己原來用dfs寫(抄)的檔案查詢,還沒改

}int main()

{ clock_t s,e;

s=clock();//開始計時

connect();

getdriver();

// query();

mysql_close(&mysql);

e=clock();//結束計時

cout<<"總用時 : "<**還沒全部完成,不知道為什麼,我沒辦法正確獲得檔案更新記錄。由於時間關係,對於非ntfs檔案系統的盤**直接複製貼上了以前自己dfs的**,還沒改。並且執行需要自己用管理員許可權執行,我沒有自己內嵌提權了

暫時就這樣吧,因為又找到了番看,所以這個就先放著了哈哈。日後記得起來的話會更新完了。不過起碼檔案查詢部分已經ok了。經過實驗,找到所有檔案(約60萬個)並寫入資料庫只要不到兩分鐘,如果不寫入資料庫,正常來說20秒不到,其中dfs建樹約為5秒(聽說雜湊表會比map好用些?)。執行的時間差不多都花在寫資料庫上了,原因不明,實在想不通別人那100萬只要1分鐘是怎麼做到的。

做過乙個比較,同樣是遍歷我電腦的c盤(約33萬檔案)找檔案,自己原來的dfs費時約1個小時,windows檔案管理器約半個小時,命令列dir /s約12分鐘,自己現在的這個**,2分鐘不到。但我還是覺得用命令列最方便。

FFT原理解釋

fft是離散傅利葉變換的快速演算法,可以將乙個訊號變換 到頻域。有些訊號在時域上是很難看出什麼特徵的,但是如 果變換到頻域之後,就很容易看出特徵了。這就是很多訊號 分析採用fft變換的原因。另外,fft可以將乙個訊號的頻譜 提取出來,這在頻譜分析方面也是經常用的。雖然很多人都知道fft是什麼,可以用...

git原理解釋

工作區域 git本地有三個工作區域 工作目錄 working directory 暫存區 stage index 本地倉庫 repository或git directory 如果在加上遠端的git倉庫 remote directory 就可以分成四個工作區域。檔案在這四個區域之間的轉換關係如下。wo...

HTTP會話原理解釋與應用

一 什麼是會話 首先解釋一下什麼是會話。在計算機術語中,會話是指乙個終端使用者與互動系統進行通訊的過程,比如從輸入賬戶密碼進入作業系統到退出作業系統就是乙個會話過程。會話較多用於網路上,tcp的三次握手就建立了乙個會話,tcp關閉連線就是關閉會話。用平述的語言可以解釋為 你拔打你女友的 號碼,你女友...