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

最近学习操作系统中,老师布置了一个作业,运用系统调用函数删除文件夹下两个重复文本类文件,Linux玩不动,于是就只能在Windows下进行了。

看了一下介绍Windows API的博客:

点击打开

基本就开始动手了。

主要利用的函数其实就那么几个:

CreateFile      创建、打开文件
ReadFile        读取文件内容
DeleteFile      文件删除
FindFirstFile   查找指定目录下的第一个文件
FindNextFile   查找下一个文件
GetFileAttributes  获取文件属性

 

主要过程就是用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:

 

2.在其中新建一些文本文档:

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

hello 文件夹内容如下所示:

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

其中 王美丽.txt 和 汪美丽.txt , 蓝玉.txt 和 徐达.txt , Apple.txt 和 hello\Apple.txt 的内容是一致的,将会被去重。

 

3.执行程序,输入目标文件夹位置:

 

4.执行结果:

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

5.需要删除其中三个文件

 

6.再次返回文件管理器,发现三个文件已被删去:

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

7.再执行,不再有重复文件:

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

 

先前以为实现这个功能就可以了,所以想用高级语言的库函数去做,但是好像跟系统调用没啥关系,所以就换成了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

 

 

 

 

 

 

 

你可能感兴趣的:(windows)