最近學習操做系統中,老師佈置了一個做業,運用系統調用函數刪除文件夾下兩個重複文本類文件,Linux玩不動,因而就只能在Windows下進行了。ios
看了一下介紹Windows API的博客:windows
點擊打開api
基本就開始動手了。數組
主要利用的函數其實就那麼幾個:app
CreateFile 建立、打開文件
ReadFile 讀取文件內容
DeleteFile 文件刪除
FindFirstFile 查找指定目錄下的第一個文件
FindNextFile 查找下一個文件
GetFileAttributes 獲取文件屬性ide
主要過程就是用FindFirstFile,FindNextFile函數掃一遍文件夾,將全部文件路徑找出來,有文件夾的話遞歸往下尋找文件,全部文件路徑放在一個字符數組中。函數
而後就是二重循環枚舉,讀出文件到緩衝區,兩兩比較,相等的話隨便刪掉一個,將待刪掉的文件編號存入容器DelList中,最後掃一遍容器進行刪除。學習
代碼:測試
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <windows.h> #define MAX_CNT 102 #define MAX_LENGTH 102 using namespace std; CHAR inputPath[MAX_PATH]; CHAR FileName[MAX_CNT][MAX_LENGTH]; int File_Cnt,OPEN_SUCCESS; vector<int> DelList; void input() { puts("Please input the Directory name: <For example: C:\\whatbeg..>"); scanf("%s",inputPath); } int StrCompare(const char *ss1, const char *ss2) //相同返回1 { int len1 = strlen(ss1), len2 = strlen(ss2); if(len1 != len2) return 0; for(int i = 0 ; i < len1 ; i++) if(ss1[i] != ss2[i]) return 0; return 1; } void GetAllFileNameInDirectory(CONST CHAR *nowpath) { DWORD Attrs; // 文件屬性 CHAR path[MAX_PATH] = {0}; // 待列路徑 CHAR concretePath[MAX_PATH]; // 具體查找路徑 HANDLE hlistfile; // 獲取到的文件句柄 WIN32_FIND_DATA fileData; // 查找到的文件數據 memmove(path, nowpath, strlen(nowpath)); lstrcpy(concretePath, path); // 複製路徑到具體查找路徑 lstrcat(concretePath, "\\*"); // 路徑拼接通配符 lstrcat(path, "\\"); hlistfile = FindFirstFile(concretePath, &fileData); // 查找路徑下第一個文件/目錄,得到句柄 if(hlistfile == INVALID_HANDLE_VALUE) { // 判斷句柄是否獲取到 printf("Error: %d\n",GetLastError()); return; } else { do { Attrs = fileData.dwFileAttributes; if(Attrs & FILE_ATTRIBUTE_DIRECTORY) { //判斷文件是不是目錄 CHAR SubDirectory[MAX_PATH]; lstrcpy(SubDirectory, path); lstrcat(SubDirectory, fileData.cFileName); //忽略 . 或 .. 的文件名 if(!StrCompare(fileData.cFileName, ".") && !StrCompare(fileData.cFileName, "..")) GetAllFileNameInDirectory(SubDirectory); //該文件是目錄,遞歸查找 } else { //是文件而非目錄 //printf("%s\n",fileData.cFileName); lstrcpy(FileName[++File_Cnt], path); lstrcat(FileName[File_Cnt], fileData.cFileName); } }while(FindNextFile(hlistfile, &fileData)); // 查找下一個文件 } return; } void OpenFile(HANDLE &handle, int FS) { //打開文件 handle = CreateFile( FileName[FS], // 文件名 GENERIC_READ, // 讀取權限 0, // 阻止其餘進程訪問 NULL, // 子進程不可繼承本句柄 OPEN_EXISTING, // 僅當該文件或設備存在時,打開它 FILE_ATTRIBUTE_NORMAL, // 普通文件 NULL // 不適用模板文件 ); if (handle == INVALID_HANDLE_VALUE) { printf("沒法打開文件 \"%s\"\n", FileName[FS]); OPEN_SUCCESS = false; return; } } void CompareAndGetDelList() { HANDLE File_01,File_02; DWORD FileSize_01,FileSize_02; DWORD ReadSize_01,ReadSize_02; char *Buffer_01, *Buffer_02; DelList.clear(); bool HaveDiffrent; for(int First = 1 ; First <= File_Cnt ; First++) { HaveDiffrent = false; for(int Second = First + 1 ; Second <= File_Cnt ; Second++) { OPEN_SUCCESS = true; OpenFile(File_01,First); OpenFile(File_02,Second); FileSize_01 = GetFileSize(File_01, NULL); FileSize_02 = GetFileSize(File_02, NULL); // printf("First,Second = %d %d ",First,Second); // printf("Filesize1,2 = %d %d ",FileSize_01,FileSize_02); // cout<<"OPENSUCCESS = "<<(OPEN_SUCCESS?1:0)<<endl; if(OPEN_SUCCESS && FileSize_01 == FileSize_02) { Buffer_01 = (CHAR *)malloc(FileSize_01 + 3); Buffer_01[FileSize_01] = '\0'; Buffer_02 = (CHAR *)malloc(FileSize_02 + 3); Buffer_02[FileSize_02] = '\0'; ReadFile(File_01,Buffer_01,FileSize_01,&ReadSize_01,NULL); ReadFile(File_02,Buffer_02,FileSize_02,&ReadSize_02,NULL); // printf(Buffer_01); puts(""); // printf(Buffer_02); puts(""); // printf("ReadSize = %d\n",ReadSize_01); for(int sek = 0; sek < ReadSize_01; sek++) if(Buffer_01[sek] != Buffer_02[sek]) { HaveDiffrent = true; break; } if(!HaveDiffrent) DelList.push_back(First); free(Buffer_01); free(Buffer_02); } CloseHandle(File_01); CloseHandle(File_02); } } // for(int i = 0 ; i < DelList.size() ; i++) // printf("%d ",DelList[i]); // puts(""); } void DeleteFileFromDelList() { printf("須要刪除的文件:\n"); for(int i = 0 ; i < DelList.size() ; i++) { printf("%s\n", FileName[DelList[i]]); DeleteFile(FileName[DelList[i]]); } } void PrintFileName() { puts("文件以下:"); for(int i=1;i<=File_Cnt;i++) printf("%s\n",FileName[i]); printf("文件個數: %d\n",File_Cnt); puts(""); } int main() { File_Cnt = 0; input(); printf("操做列表路徑: [%s\\*] \n", inputPath); GetAllFileNameInDirectory(inputPath); PrintFileName(); CompareAndGetDelList(); DeleteFileFromDelList(); return 0; }
1.新建一個文件夾e:\\osdemo:spa
2.在其中新建一些文本文檔:
hello 文件夾內容以下所示:
其中 王美麗.txt 和 汪美麗.txt , 藍玉.txt 和 徐達.txt , Apple.txt 和 hello\Apple.txt 的內容是一致的,將會被去重。
3.執行程序,輸入目標文件夾位置:
4.執行結果:
5.須要刪除其中三個文件
6.再次返回文件管理器,發現三個文件已被刪去:
7.再執行,再也不有重複文件:
先前覺得實現這個功能就能夠了,因此想用高級語言的庫函數去作,可是好像跟系統調用沒啥關係,因此就換成了Windows API了。
下面是之前寫的Python實現:
Python Code:
# -*- coding: cp936 -*- import os filelist = [] #文件名列表 for root,dirs,files in os.walk('e:\\osdemo'): #找出文件夾內全部的文件名存放在filelist中 for filespath in files: filelist.append(os.path.join(root,filespath)) print os.path.join(root,filespath) #for fl in filelist: # print fl Siz = filelist.__len__() #文件個數 delist = [] #須要刪除的文件名列表 for i in range(0,Siz): #二重循環枚舉列表中元素,兩兩比較 for j in range(i+1,Siz): file1 = open(filelist[i],'r') #打開文件1 file2 = open(filelist[j],'r') #打開文件2 flag = 1 #標識兩個文件是否相同,相同爲1,不一樣爲0 for eachLine in file1: #每次取文件1的一行 #print "File1 = %s" %eachLine Line2 = file2.readline() #取文件2的一行 #print "File2 = %s" %Line2 if eachLine != Line2: #不一樣,flag=0,直接退出 flag = 0 break; #print "file2.readline = ",file2.readline() if(flag and file2.readline() == ''): #若是沒有發現不一樣,且file2也到了文件尾,說明文件內容相同 #print "deleted %s" %filelist[j] delist.append(filelist[j]) #把文件j的名字加入待刪除列表 file1.close() #關閉文件 file2.close() for d in delist: #枚舉待刪除列表中每一個文件名 if os.path.exists(d): #若是還存在,就刪去 os.remove(d) else: print "No such file: %s or has been deleted" %d