1 / 30

Project2: 文件夹同步工具

Project2: 文件夹同步工具. 任务 背景. 有 2 个文件夹 A 和 B ,经过之前的同步操作,文件夹 B 中的内容与文件夹 A 中内容完全一致,现在用户对 A 文件夹中部分文件进行了编辑、移动、删除或者新增的操作,请你的程序根据文件夹 A 中的内容变化对文件夹 B 进行增量更新。. 功能要求. 文件夹 A 中保持不变的文件在文件夹 B 中保持不变,不更新。 给出文件夹 A 中文件的更新情况列表,即列出与上次同步后文件夹 A 中所有发生变化的文件列表, 包括 a ) 与上次更新相比,所有新增文 件的列表 b ) 与上次更新相比,所有删除文 件的列表

chapa
Download Presentation

Project2: 文件夹同步工具

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Project2:文件夹同步工具

  2. 任务背景 • 有2个文件夹A和B,经过之前的同步操作,文件夹B中的内容与文件夹A中内容完全一致,现在用户对A文件夹中部分文件进行了编辑、移动、删除或者新增的操作,请你的程序根据文件夹A中的内容变化对文件夹B进行增量更新。

  3. 功能要求 • 文件夹A中保持不变的文件在文件夹B中保持不变,不更新。 • 给出文件夹A中文件的更新情况列表,即列出与上次同步后文件夹A中所有发生变化的文件列表,包括 • a) 与上次更新相比,所有新增文件的列表 • b) 与上次更新相比,所有删除文件的列表 • c) 与上次更新相比,所有发生变动的文件的列表 • 只对文件夹A中发生变化的文件在文件夹B中更新,即针对上述3中变化的文件,删除文件夹B中的相应原文件,并将A中最新文件复制到文件夹B中。 • 注意:删除时需要提示用户是否确定删除源文件。

  4. 其他要求 • 简单易用、界面友好 • 足够的提示信息 • 输入错误的处理 • 更新速度快 满分:85分

  5. 提高要求 • 将上述工具移植到windows平台下。 • 在文件夹B中保留更新前的文件(比如,重新以特定的命名方式命名或者保存在特定的文件夹中的方式)。 • 开发图形界面 满分:100

  6. 解题思路 • 简单想法: • 遍历文件夹A、B,对于A中的任一文件f1, 在B中查找与f1同名文件f2 • 如果找到f2,读取f1和f2的文件信息是否一致 • 一致:表示文件没有发生变化,什么也不做 • 不一致:用f1覆盖f2 • 如果没有找到,表示该文件是新文件,则将其复制到文件夹B中 • 还有没有其他问题?

  7. 实现细节 • 如何遍历整个文件夹? • Linux命令 • ls –R • Find • 调用操作系统提供API(应用编程接口) • opendir()、readdir()、closedir() • 如何读取文件信息? • Linux相关命令: • 系统函数:

  8. 问题1:遍历得到目录下所有的文件 • 方法1:利用linux命令的结果 • ls –R • find

  9. ls-R

  10. find命令 • find是linux中最有用的命令之一 • 用于在一个目录(及子目录)中搜索文件 • 可以指定一些匹配条件,如按文件名、文件类型、用户甚至是时间戳查找文件 • 举例: • find . -name "*.c” • 在当前目录及其子目录中查找任何扩展名为c的文件 • find . -type f • 查找当前目录中的每一个普通文件 • find / -mtime -5 • 在系统根目录下查找更改时间在5日以内的文件

  11. 如何在程序中利用linux命令的结果 • system()函数:调用“/bin/sh -c command”执行特定的命令,阻塞当前进程直到command命令执行完毕 • 如何得到命令执行的结果 • system的返回值不能待会命令的执行结果 • 输入输出重定向 原型: intsystem(const char *command); 返回值: 如果无法启动shell运行命令,system将返回127;出现不能执行system调用的其他错误时返回-1。如果system能够顺利执行,返回那个命令的退出码。

  12. 输入输出重定向 • Linux重定向是指对原来系统命令的默认执行方式进行改变 • <和>实现输出输入的重定向 • 使用< 或 > 时,相当于使用 0< 或 1> • 简单举例 • cmd > file • 把cmd命令的输出重定向到文件file中。如果file已经存在,则清空原有文件,例如:ls-l>filenames.txt • cmd < file • 使cmd命令从file读入

  13. Linux的管道 • ls-l|wc-l

  14. 方法1:实现提示 • 在你的程序中,利用system函数得到目录下的所有文件,并将结果保存到文件中 • system(“find.>filelist.txt”); • system(“ls -l –R > filelist1.txt”);

  15. 方法2:利用操作系统提供的API • 目录操作相关的API • opendir • 打开目录,并返回DIR*形态的目录流,接下来对目录的读取和搜索都要使用此返回值。 • readdir • 读取目录 • 返回一个代表目录里下一个项目的指针 • closedir • 关闭目录

  16. opendir:打开目录 • 表头文件 • #include<sys/types.h> • #include<dirent.h> • 定义函数 • DIR * opendir(const char * name); • 函数说明 • opendir()用来打开参数name指定的目录,并返回DIR*形态的目录流,接下来对目录的读取和搜索都要使用此返回值。 • 返回值 • 成功则返回DIR* 型态的目录流,打开失败则返回NULL。

  17. readdir函数 • 表头文件 • #include<sys/types.h> • #include<dirent.h> • 函数原型 • structdirent * readdir(DIR * dir); • 函数说明 • 返回一个代表目录 dirp里下一个项目的指向 dirent结构的指针。如果到达目录流结尾或出错它返回 NULL。 • 返回值 • 成功则返回下个目录进入点。有错误发生或读取到目录文件尾则返回NULL。

  18. readdir函数(2) 在 Linux 系统里,dirent结构定义如下: structdirent { ino_td_ino; /* inode number */ off_td_off; /* 下一个项目的偏移 */ unsigned short d_reclen; /* 本记录的长度 */ unsigned char d_type; /* 文件类型;不是被所有文件系统支持 */ char d_name[256]; /* 文件名 */ };

  19. closedir:关闭目录 • 表头文件 • #include<sys/types.h> • #include<dirent.h> • 定义函数 • intclosedir(DIR *dir); • 函数说明 • closedir()关闭参数dir所指的目录流。 • 返回值 • 关闭成功则返回0,失败返回-1,错误原因存于errno中。

  20. 编程提示 pDir=opendir(path) while( (ent=readdir(pDir))!=NULL ) { //dosomething; } closedir(pDir);

  21. 问题2:如何确定文件是否更新过? • Linux文件的时间信息 • 如何读取文件信息? • Linux相关命令:stat • 系统函数: • stat()、fstat()、lstat()

  22. Linux中文件时间 • Windows下: • 创建时间 • 修改时间 • 访问时间 • 访问时间 • 修改时间 • 状态改变时间 • 该文件最后一次被修改的时间 • 通过chmod、chown命令修改一次文件属性,这个时间就会更新。

  23. 如何获取文件信息 • Linux相关命令:stat • 系统函数: • stat()、fstat()、lstat()

  24. lstat函数 • 返回与文件有关的信息结构 • intlstat(const char *path, struct stat *buf); structstat { dev_tst_dev; /* 文件所在设备的标识 */ ino_tst_ino; /* 文件结点号 */ mode_tst_mode; /* 文件保护模式 */ nlink_tst_nlink; /* 硬连接数 */ uid_tst_uid; /* 文件用户标识 */ gid_tst_gid; /* 文件用户组标识 */ dev_tst_rdev; /* 文件所表示的特殊设备文件的设备标识 */ off_tst_size; /* 总大小,字节为单位 */ blksize_tst_blksize; /* 文件系统的块大小 */ blkcnt_tst_blocks; /* 分配给文件的块的数量,512字节为单元 */ time_tst_atime; /* 最后访问时间 */ time_tst_mtime; /* 最后修改时间 */ time_tst_ctime; /* 最后状态改变时间 */ };

  25. 代码分析:遍历目录 #include <unistd.h> #include <stdio.h> #include <dirent.h> #include <string.h> #include <sys/stat.h> void List( char *path, int indent ) { structdirent* ent = NULL; DIR *pDir; char dir[512]; struct stat statbuf; if( (pDir=opendir(path))==NULL ) { fprintf( stderr, "Cannot open directory:%s\n", path ); return; }

  26. while( (ent=readdir(pDir))!=NULL ) { //得到读取文件的绝对路径名 snprintf( dir, 512,"%s/%s", path, ent->d_name ); //得到文件信息 lstat( dir, &statbuf); //判断是目录还是文件 if( S_ISDIR(statbuf.st_mode) ) { //排除当前目录和上级目录 if(strcmp( ".",ent->d_name) == 0 || strcmp( "..",ent->d_name) == 0) { continue; } //如果是子目录,递归调用函数本身,实现子目录中文件遍历 printf( "%*s子目录:%s/\n", indent, "", ent->d_name ); //递归调用,遍历子目录中文件 List( dir, indent+4 ); } else { printf( "%*s文件:%s\n", indent, "", ent->d_name ); } } closedir(pDir); }

  27. int main(intargc, char* argv[]) { if(argc == 2) { List( argv[1], 2 ); } else { char *s = "."; List( s, 2 ); } return 0; }

  28. 其他问题 • 提高效率 • 可以将文件信息保存起来 • 移植到windows平台 • linux下的API换成windows平台的响应API

More Related