初識【Windows API】--文本去重

最近學習操做系統中,老師佈置了一個做業,運用系統調用函數刪除文件夾下兩個重複文本類文件,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;
}
View Code

 

效果測試

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
View Code
相關文章
相關標籤/搜索