博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
初识【Windows API】--文本去重
阅读量:4560 次
发布时间:2019-06-08

本文共 5050 字,大约阅读时间需要 16 分钟。

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

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

基本就开始动手了。

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

CreateFile      创建、打开文件

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

 

主要过程就是用FindFirstFile,FindNextFile函数扫一遍文件夹,将所有文件路径找出来,有文件夹的话递归往下寻找文件,所有文件路径放在一个字符数组中。

然后就是二重循环枚举,读出文件到缓冲区,两两比较,相等的话随便删掉一个,将待删掉的文件编号存入容器DelList中,最后扫一遍容器进行删除。

代码:

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_CNT 102#define MAX_LENGTH 102using namespace std;CHAR inputPath[MAX_PATH];CHAR FileName[MAX_CNT][MAX_LENGTH];int File_Cnt,OPEN_SUCCESS;vector
DelList;void input() { puts("Please input the Directory name:
"); 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)<
View Code

 

效果测试

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

 

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

 

hello 文件夹内容如下所示:

 

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

 

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

 

4.执行结果:

 

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

 

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

 

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

 

 

先前以为实现这个功能就可以了,所以想用高级语言的库函数去做,但是好像跟系统调用没啥关系,所以就换成了Windows API了。

下面是以前写的Python实现:

Python Code:

# -*- coding: cp936 -*-import osfilelist = []                                    #文件名列表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 flSiz = 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

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/whatbeg/p/4386794.html

你可能感兴趣的文章
ORA-12505: TNS: 监听程序当前无法识别连接描述符中所给出的SID等错误解决方法
查看>>
实用类-<Math类常用>
查看>>
构建之法阅读笔记之四
查看>>
10.15习题2
查看>>
Windows Server 2008 R2 备份与恢复详细实例
查看>>
Ubuntu上kubeadm安装Kubernetes集群
查看>>
关于java学习中的一些易错点(基础篇)
查看>>
MFC的多国语言界面的实现
查看>>
四则运算个人项目 最终版
查看>>
angular学习之angular-phonecat项目的实现
查看>>
KMP算法
查看>>
DS博客作业07--查找
查看>>
javascript常用对象
查看>>
loadrunner测试socket协议程序知识汇总(转)
查看>>
SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表?...
查看>>
凯撒密码、GDP格式化输出、99乘法表
查看>>
SQL Server 2008 分区函数和分区表详解(转)
查看>>
ASP.NET缓存全解析(转)
查看>>
java线程系列---java5中的线程池
查看>>
SQL表连接
查看>>