zoukankan      html  css  js  c++  java
  • 初识【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
    ",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
    ",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"
    ", 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] = '';
    
                    Buffer_02 = (CHAR *)malloc(FileSize_02 + 3);
                    Buffer_02[FileSize_02] = '';
    
                    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
    ",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("需要删除的文件:
    ");
        for(int i = 0 ; i < DelList.size() ; i++)
        {
            printf("%s
    ", FileName[DelList[i]]);
            DeleteFile(FileName[DelList[i]]);
        }
    }
    
    void PrintFileName() {
        puts("文件如下:");
        for(int i=1;i<=File_Cnt;i++)
            printf("%s
    ",FileName[i]);
        printf("文件个数: %d
    ",File_Cnt);
        puts("");
    }
    
    int main()
    {
        File_Cnt = 0;
        input();
        printf("操作列表路径: [%s\*] 
    ", inputPath);
        GetAllFileNameInDirectory(inputPath);
        PrintFileName();
        CompareAndGetDelList();
        DeleteFileFromDelList();
        return 0;
    }
    View Code

    效果测试

    1.新建一个文件夹e:\osdemo:

     

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

     

    hello 文件夹内容如下所示:

     

    其中 王美丽.txt 和 汪美丽.txt , 蓝玉.txt 和 徐达.txt , Apple.txt 和 helloApple.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

     

  • 相关阅读:
    家长如何助力孩子适应小学生活
    一年级线上家长会
    gdb常用调试命令
    二叉树-后序遍历
    机器人
    Oracle创建只读账号的详细步骤
    ORACLE RAC日常运维-调整RAC+DG环境redo大小
    Redis 延迟分析
    oracle dataguard 重启步骤
    catalog start with + switch database to copy的妙用
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4386794.html
Copyright © 2011-2022 走看看