最近学习操作系统中,老师布置了一个作业,运用系统调用函数删除文件夹下两个重复文本类文件,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 ;
for(int i = ; i < len1 ; i++) if(ss1[i] != ss2[i]) return ;
return ;
} void GetAllFileNameInDirectory(CONST CHAR *nowpath) { DWORD Attrs; // 文件属性
CHAR path[MAX_PATH] = {}; // 待列路径
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, // 读取权限
, // 阻止其他进程访问
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 = ; First <= File_Cnt ; First++) { HaveDiffrent = false; for(int Second = First + ; 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 + );
Buffer_01[FileSize_01] = '\0'; Buffer_02 = (CHAR *)malloc(FileSize_02 + );
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 = ; 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 = ; i < DelList.size() ; i++)
{
printf("%s\n", FileName[DelList[i]]);
DeleteFile(FileName[DelList[i]]);
}
} void PrintFileName() {
puts("文件如下:");
for(int i=;i<=File_Cnt;i++)
printf("%s\n",FileName[i]);
printf("文件个数: %d\n",File_Cnt);
puts("");
} int main()
{
File_Cnt = ;
input();
printf("操作列表路径: [%s\\*] \n", inputPath);
GetAllFileNameInDirectory(inputPath);
PrintFileName();
CompareAndGetDelList();
DeleteFileFromDelList();
return ;
}

效果测试

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 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

初识【Windows API】--文本去重的更多相关文章

  1. Windows API 函数列表 附帮助手册

    所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...

  2. 学习之路三十九:新手学习 - Windows API

    来到了新公司,一开始就要做个程序去获取另外一个程序里的数据,哇,挑战性很大. 经过两周的学习,终于搞定,主要还是对Windows API有了更多的了解. 文中所有的消息常量,API,结构体都整理出来了 ...

  3. Windows API Finishing

    input { font-size: 14px; height: 26px } td { border-style: none; border-color: inherit; border-width ...

  4. Windows API 调用示例

    Ø  简介 本文主要记录 Windows API 的调用示例,因为这项技术并不常用,属于 C# 中比较孤僻或接触底层的技术,并不常用.但是有时候也可以借助他完成一些 C# 本身不能完成的功能,例如:通 ...

  5. 《随机出题软件》&《随机分队软件》源码(Windows API)

    1 引言 1.1 编写目的: 为了对院级活动<最强大脑>提供软件支持,同时为了练习使用windows API. 1.2 项目背景: 来自计算机学院学生会信息部指派的任务,规定时间完成软件的 ...

  6. Windows API函数大全(完整)

    Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...

  7. [windows菜鸟]Windows API函数大全(完整)

    Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...

  8. WINDOWS API 大全(二)

    9. API之设备场景函数 CombineRgn 将两个区域组合为一个新区域CombineTransform 驱动世界转换.它相当于依顺序进行两次转换CreateCompatibleDC 创建一个与特 ...

  9. WINDOWS API 大全(一)

    1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同 ...

随机推荐

  1. 【NopCommerce源码架构学习-二】单例模式实现代码分析

    单例模式是是常用经典十几种设计模式中最简单的..NET中单例模式的实现也有很多种方式.下面我来介绍一下NopCommerce中单例模式实现. 我之前的文章就分析了一下nop中EngineContext ...

  2. Asp.net 面向接口可扩展框架之使用“类型转化基础服务”测试四种Mapper(AutoMapper、EmitMapper、NLiteMapper及TinyMapper)

    Asp.net 面向接口可扩展框架的“类型转化基础服务”是我认为除了“核心容器”之外最为重要的组成部分 但是前面博文一出,争议很多,为此我再写一篇类型转化基础服务和各种Mapper结合的例子,顺便对各 ...

  3. 使用NPOI组件完成的Excel导出导入(附源代码,测试通过)

    最近遇到一个Excel导入导出的问题,要支持winform和webform,这里我是一个认真严谨的coder,所以决定把这个记录下来!和大家一起分享一下!如果需要的同学可以下载哦! 对于NPOI这个组 ...

  4. SpringMVC中servletFileUpload.parseRequest(request)解析为空获取不到数据问题

    原因分析 首先我们来看下Spring mvc 中文件上传的配置 <bean id="multipartResolver" class="org.springfram ...

  5. java web学习总结(六) -------------------servlet开发(二)

    一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些 ...

  6. 几款开源的hybird移动app框架分析

    几款开源的Hybrid移动app框架分析 Ionic Onsen UI 与 ionic 相比 jQuery Mobile Mobile Angular UI 结论 很多移动开发者喜欢使用原生代码开发, ...

  7. jQuery实现checkbox反选(转载)

    //反选 $("#btnInvert").click(function () { //1.方法一实现反选 $("#chk input:checkbox").ea ...

  8. jquery点击切换背景色

    刚在自己的前端技术群里有个小伙伴儿问到这个问题,点击的时候进行红色背景和白色背景的切换,然后我就临时想到了一个解决方法,在这里记录一下吧,希望还有别的刚学习前端的小伙伴儿能用到,大神就请绕道咯!另外提 ...

  9. WWDC 后苹果最新 App Store 审核条款!

        WWDC 2016 大会之后,苹果公司发布了四个全新平台:iOS,macOS,watchOS 和 tvOS.并且在此之后,苹果应用商店审核条款也同时进行了更新——貌似不算进行了更新,简直就是重 ...

  10. CSS3-01 简介

    概述 HTML 文档由包含 HTML 标签的 HTML 元素组成,HTML 标签被用于定义文档的内容.HTML 文档内容没有额外的样式,以纯文本流的方式渲染到浏览器页面.需要借助层叠样式表(CSS)来 ...