项目要求

1.基本

  用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件;实现复制到指定文件夹的全部文件夹。

2.扩充功能

  显示进度条;拷贝耗时统计;类似linux的tree,不能直接用system()与exec()等函数;根据文件类型拷贝;搜索文件;删除文件等。(暂时加了这么一些功能)

8月17日补:移动、复制到的目录已包含该文件则选择覆盖或者加命名。

实现思路

  先完成基本,逐步完成扩展再优化重构代码。

实现过程

基本功能

  基于linux,通过线程池实现的。核心就是线程池的三大基本功能--线程例程、添加线程、销毁线程池。由这三个为基础,对项目进行展开。基本功能,即通过递归读取目录,通过strucr dirent *p这个结构体来实现判断文件类型。如果是普通文件,直接在新目录用文件IO的读写实现拷贝功能(包括标准IO、系统IO,还有共享内存也可以实现),拷贝那里用“添加线程”,保证可以多线程实现拷贝;如果是目录文件,就先创建文件夹--mkdir(),再sprintf拼接字符串以及函数的递归实现子级目录的拷贝。

->拷贝代码

  1. void *myregcp(void *myarg)
  2. {
  3. struct copypath *mypath=(struct copypath *)myarg;
  4.  
  5. //系统IO的复制
  6. int fd1,fd2;
  7. fd1=open(mypath->oldpath,O_RDONLY);
  8. fd2=open(mypath->newpath,O_CREAT|O_TRUNC|O_RDWR,0777);
  9. if(fd1==-1)
  10. {
  11. perror("打开1失败\n");
  12. return NULL;
  13. }
  14. if(fd2==-1)
  15. {
  16. perror("打开2失败\n");
  17. return NULL;
  18. }
  19. char buf[SIZE];
  20. int nread,nwrite;
  21. while(1)
  22. {
  23. bzero(buf,SIZE);
  24. nread=read(fd1,buf,SIZE);
  25. if(nread==0)
  26. break;
  27. cs=cs+nread;
  28. write(fd2,buf,nread);
  29. }
  30. close(fd1);
  31. close(fd2);
  32. return NULL;
  33. }

->递归读取全部目录

  1. int myreaddir(struct copypath *pp,struct threadpool *pool)
  2. {
  3. DIR *dirp=opendir(pp->oldpath);
  4. if(dirp==NULL)
  5. {
  6. perror("失败:\n");
  7. return -1;
  8. }
  9. struct dirent *p;
  10. while((p=readdir(dirp))!=NULL)
  11. {
  12. if(p->d_type==DT_REG) //普通文件
  13. {
  14. struct copypath *mypath=malloc(sizeof(struct copypath));
  15. sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  16. sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
  17. add_task(myregcp,mypath,pool); //实现
  18. }
  19. if(p->d_type==DT_DIR) //文件夹
  20. {
  21. if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
  22. {
  23. struct copypath *mydirpath=malloc(sizeof(struct copypath));
  24. sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  25. sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
  26. mkdir(mydirpath->newpath,0777);
  27. myreaddir(mydirpath,pool);
  28. }
  29. }
  30. }
  31. closedir(dirp);
  32. return 1;
  33. }

  这样就大概完成基本功能,用多线程实现大文件夹的拷贝。

扩充功能

->进度条

  定义两个全局变量,一个用于计算总字节数,另一个计算每次复制的字节数,再用一个显示函数实现进度条的显示。这里要注意缓冲区的问题,所以我用了"fflush(NULL)"这个函数,让它每打印一个'|'的时候,就刷新一次缓冲区。计算总的字节数直接递归全部目录,用"struct stat info"这个结构体里面的"info.st_size"累加,即可得到总的字节数;拷贝功能函数里面有个"cs"变量,就是存放拷贝字节数。显示进度条就用简单的判断,加相除实现。因为是显示20个|,所以我乘20。

  1.   num=(float)cs; //正在复制字节数
  2.   k=(num/s)*20;

->耗时

  有三种思路,用clock()、time()、sleep(1)等都可以实现计时,直接在拷贝前和拷贝后加赋值,然后相减,即可。起初自己是用clock()这个函数,但是每次都是三秒。。。然后转到sleep(),让它自己while()累加实现。

->代码实现树

  还是递归的思想,递归如果是普通文件就打印,是目录文件夹就字符串拼接再递归打印子文件夹下的子文件。

  1. void dirtree(char dirpath[],int level)
  2. {
  3. int i;
  4. char *dirname=NULL;
  5. int dirlen;
  6. DIR *dp=opendir(dirpath);
  7. if(dp==NULL)
  8. {
  9. perror("失败:\n");
  10. return;
  11. }
  12. struct dirent *ep;
  13. while((ep=readdir(dp))!=NULL)
  14. {
  15. if(strncmp(ep->d_name, ".", 1) == 0)
  16. continue;
  17. for(i=0;i<level;i++)
  18. {
  19. printf("|");
  20. printf(" ");
  21. }
  22. printf("|--- ");
  23. printf("\033[1;32;40m %s \033[0m\n",ep->d_name);
  24. if(ep->d_type==DT_DIR)
  25. {
  26. //当前目录长度
  27. dirlen=strlen(dirpath)+1;
  28. //备份
  29. dirname=(char *)malloc(dirlen);
  30. memset(dirname,0,dirlen);
  31. memcpy(dirname,dirpath,dirlen);
  32.  
  33. strcat(dirpath,"/");
  34. strcat(dirpath,ep->d_name);
  35. dirtree(dirpath,level+1); //递归实现树效果
  36. //恢复之前的目录名
  37. memcpy(dirpath,dirname,dirlen);
  38. free(dirname);
  39. dirname = NULL;
  40. }
  41. }
  42. closedir(dp);
  43. }

->按类型拷贝文件

  也比较简单,另建一个递归读目录的函数,在普通文件加个if条件判断就可以。

  1.   if(strstr(p->d_name,ftype)!=NULL)

->搜索文件

  类似于win的文件检索功能,在输入那个文件下面实现相似文件名的检索,并打印相关路径。也是递归读取目录,核心的改变代码也就一句。用"strstr()"寻找相应的子字符串,打印。

  1.   if(strstr(p->d_name,filename)!=NULL)

->删除文件夹

  删除稍微要注意一下如果文件夹下面还有其他文件,就不能直接用"rmdir"删除文件夹。先用remove()删除文件,之后再删除子文件夹。也是用递归思想实现的。

实现效果

  现在还传不了,后期再传吧。

全部代码

  1. #include "myhead.h"
  2. #define SIZE 1024*1024
  3. long int s=0; //总字节数
  4. long int cs=0; //计算每次复制的字节数
  5. int tm=0; //计时--以秒为单位
  6. int flag; //结束标志位
  7. /***************************相关结构体的定义******************************/
  8. struct copypath
  9. {
  10. char oldpath[256];
  11. char newpath[256];
  12. char target[50];
  13. };
  14. //创建任务链表结构体
  15. struct tasklist
  16. {
  17. void *(*taskp)(void *);
  18. void *taskarg;
  19. struct tasklist *next;
  20. };
  21. //创建任务链表表头
  22. struct tasklist *myhead;
  23. //初始化任务链表
  24. struct tasklist* task_init()
  25. {
  26. struct tasklist *mytask=malloc(sizeof(struct tasklist));
  27. mytask->taskp=NULL;
  28. mytask->taskarg=NULL;
  29. mytask->next=NULL;
  30. return mytask;
  31. }
  32. //创建线程池
  33. struct threadpool
  34. {
  35. int threadnum;//统计当前线程数量
  36. pthread_t *threadid;//存放当前线程的ID号
  37. struct tasklist *taskhead;//保存任务链表的头结点
  38. pthread_mutex_t threadmutex;//互斥锁
  39. int tasknum;//统计任务链表中的数量
  40. pthread_cond_t threadcond;//条件变量
  41. bool threadflag;//用于判断线程池是否开启
  42. };
  43.  
  44. //线程的多任务函数
  45. void *routine(void *arg)
  46. {
  47. struct threadpool *pool=(struct threadpool *)arg;
  48. //负责从任务链表的头结点的下一个位置取出任务然后处理
  49. struct tasklist *p;
  50. while(1)
  51. {
  52. //上锁
  53. pthread_mutex_lock(&(pool->threadmutex));
  54. //判断数量是否为0
  55. while(pool->threadflag==true && pool->tasknum==0)
  56. {
  57. //printf("%ld线程阻塞--wait\n",pthread_self());
  58. pthread_cond_wait(&(pool->threadcond),&(pool->threadmutex));
  59. }
  60. if(pool->threadflag==false&&pool->tasknum==0)
  61. {
  62. pthread_mutex_unlock(&(pool->threadmutex));
  63. pthread_exit(NULL);
  64. }
  65. //取出节点处理
  66. p=pool->taskhead->next;
  67. pool->taskhead->next=p->next;
  68. p->next=NULL;
  69. //更新任务数量
  70. pool->tasknum--;
  71. //printf("%ld线程正在执行任务\n",pthread_self());
  72. //解锁
  73. pthread_mutex_unlock(&(pool->threadmutex));
  74. (p->taskp)(p->taskarg);
  75. free(p);
  76. }
  77. }
  78. //初始化线程池结构体
  79. struct threadpool *thread_init(int num)
  80. {
  81. struct threadpool *mythread=malloc(sizeof(struct threadpool));//申请堆空间
  82. mythread->threadnum=num;
  83. mythread->threadid=malloc(num*sizeof(pthread_t));
  84. //初始化链表的表头
  85. mythread->taskhead=myhead;
  86. //锁初始化
  87. pthread_mutex_init(&(mythread->threadmutex),NULL);
  88. //条件变量初始化
  89. pthread_cond_init(&(mythread->threadcond),NULL);
  90. mythread->tasknum=0;
  91. mythread->threadflag=true;
  92. for(int i=0;i<num;i++)
  93. pthread_create(&(mythread->threadid[i]),NULL,routine,mythread);
  94. return mythread;
  95. }
  96. //添加任务函数
  97. int add_task(void *(*p)(void *),void *newarg,struct threadpool *pool)
  98. {
  99. //找到尾部
  100. struct tasklist *q=pool->taskhead;
  101. while(q->next!=NULL)
  102. q=q->next;
  103. //准备新结点
  104. struct tasklist *newnode=malloc(sizeof(struct tasklist));
  105. newnode->taskp=p;
  106. newnode->taskarg=newarg;
  107. newnode->next=NULL;
  108.  
  109. //上锁
  110. pthread_mutex_lock(&(pool->threadmutex));
  111. //尾插
  112. q->next=newnode;
  113. //更新任务数量
  114. pool->tasknum++;
  115. pthread_mutex_unlock(&(pool->threadmutex));
  116. //唤醒条件
  117. pthread_cond_signal(&(pool->threadcond));
  118. return 0;
  119. }
  120. /***************************************************************************/
  121. // 功能函数
  122. /***************************************************************************/
  123. //主目录名
  124. void *mycopyname(void *myarg)
  125. {
  126. struct copypath *mypath=(struct copypath *)myarg;
  127. char fpath[15]; //求出主目录的名字
  128. char temp[100];
  129. strcpy(temp,mypath->oldpath);
  130. char *p=strtok(temp,"/");
  131. //获取文件名
  132. while(p!=NULL)
  133. {
  134. bzero(fpath,15);
  135. strcpy(fpath,p);
  136. p=strtok(NULL,"/");
  137. }
  138. strcpy(((struct copypath *)myarg)->target,fpath);
  139. }
  140. //普通文件复制
  141. void *myregcp(void *myarg)
  142. {
  143. struct copypath *mypath=(struct copypath *)myarg;
  144.  
  145. //系统IO的复制
  146. int fd1,fd2;
  147. fd1=open(mypath->oldpath,O_RDONLY);
  148. fd2=open(mypath->newpath,O_CREAT|O_TRUNC|O_RDWR,0777);
  149. if(fd1==-1)
  150. {
  151. perror("打开1失败\n");
  152. return NULL;
  153. }
  154. if(fd2==-1)
  155. {
  156. perror("打开2失败\n");
  157. return NULL;
  158. }
  159. char buf[SIZE];
  160. int nread,nwrite;
  161. while(1)
  162. {
  163. bzero(buf,SIZE);
  164. nread=read(fd1,buf,SIZE);
  165. //cs=cs+nread;
  166. if(nread==0)
  167. break;
  168. cs=cs+nread;
  169. write(fd2,buf,nread);
  170. }
  171. close(fd1);
  172. close(fd2);
  173. return NULL;
  174. }
  175. //遍历读目录
  176. int myreaddir(struct copypath *pp,struct threadpool *pool)
  177. {
  178. DIR *dirp=opendir(pp->oldpath);
  179. if(dirp==NULL)
  180. {
  181. perror("失败:\n");
  182. return -1;
  183. }
  184. struct dirent *p;
  185. while((p=readdir(dirp))!=NULL)
  186. {
  187. if(p->d_type==DT_REG) //普通文件
  188. {
  189. struct copypath *mypath=malloc(sizeof(struct copypath));
  190. sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  191. sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
  192. add_task(myregcp,mypath,pool); //实现
  193. }
  194. if(p->d_type==DT_DIR) //文件夹
  195. {
  196. if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
  197. {
  198. struct copypath *mydirpath=malloc(sizeof(struct copypath));
  199. sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  200. sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
  201. mkdir(mydirpath->newpath,0777);
  202. myreaddir(mydirpath,pool);
  203. }
  204. }
  205. }
  206. closedir(dirp);
  207. return 1;
  208. }
  209. //递归算字节数
  210. int size_sum(struct copypath *pp)
  211. {
  212. DIR *dirp=opendir(pp->oldpath);
  213. if(dirp==NULL)
  214. {
  215. perror("失败:\n");
  216. return -1;
  217. }
  218. struct dirent *p;
  219. struct stat info;
  220. while((p=readdir(dirp))!=NULL)
  221. {
  222. if(p->d_type==DT_REG) //普通文件
  223. {
  224. struct copypath *mypath=malloc(sizeof(struct copypath));
  225. sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  226. //计算字节数
  227. stat(mypath->oldpath,&info);
  228. s=s+info.st_size;
  229. }
  230. if(p->d_type==DT_DIR) //文件夹
  231. {
  232. if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
  233. {
  234. struct copypath *mydirpath=malloc(sizeof(struct copypath));
  235. sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  236. size_sum(mydirpath);
  237. }
  238. }
  239. }
  240. closedir(dirp);
  241. return 1;
  242. }
  243. //实现进度条
  244. void *pro_bar(void *myarg)
  245. {
  246. int i,j=0;
  247. float k,num;
  248. printf("进度:");
  249. while(1)
  250. {
  251. j=k;
  252. num=(float)cs; //正在复制字节数
  253. k=(num/s)*20; //
  254. k=(int)k;
  255. if(k-j>=1)
  256. {
  257. for(i=0;i<k-j;i++)
  258. {
  259. printf("\033[1;31;42m | \033[0m");
  260. }
  261. fflush(NULL);
  262. }
  263. usleep(10000);
  264. if(s==cs)
  265. {
  266. printf("\033[1;31;42m | \033[0m");
  267. fflush(NULL);
  268. usleep(200);
  269. break;
  270. }
  271. }
  272. printf("\n任务完成\n");
  273. return NULL;
  274. }
  275. //lseep计时
  276. void *my_time(void *myarg)
  277. {
  278. while(1)
  279. {
  280. sleep(1);
  281. tm++;
  282. if(s==cs)
  283. {
  284. break;
  285. }
  286. }
  287. }
  288. //显示选择拷贝类型界面
  289. int showdow()
  290. {
  291. int n;
  292. printf("**********************\n");
  293. printf(" 请输入你要拷贝的文件 \n");
  294. printf(" 1.复制全部文件; \n");
  295. printf(" 2.选择类型复制; \n");
  296. printf(" 3.原目录文件树; \n");
  297. printf(" 4.查找某个文件; \n");
  298. printf(" 5.删除某个文件. \n");
  299. printf("**********************\n");
  300. scanf("%d",&n);
  301. return n;
  302. }
  303. //递归读取文件类型的字节数
  304. int ftypesize_sum(struct copypath *pp,char *ftype)
  305. {
  306. DIR *dirp=opendir(pp->oldpath);
  307. if(dirp==NULL)
  308. {
  309. perror("失败:\n");
  310. return -1;
  311. }
  312. struct dirent *p;
  313. struct stat info;
  314. while((p=readdir(dirp))!=NULL)
  315. {
  316. if(p->d_type==DT_REG) //普通文件
  317. {
  318. if(strstr(p->d_name,ftype)!=NULL) //文件类型
  319. {
  320. struct copypath *mypath=malloc(sizeof(struct copypath));
  321. sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  322. //计算字节数
  323. stat(mypath->oldpath,&info);
  324. s=s+info.st_size;
  325. }
  326. }
  327. if(p->d_type==DT_DIR) //文件夹
  328. {
  329. if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
  330. {
  331. struct copypath *mydirpath=malloc(sizeof(struct copypath));
  332. sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  333. ftypesize_sum(mydirpath,ftype);
  334. }
  335. }
  336. }
  337. closedir(dirp);
  338. return 1;
  339. }
  340. //递归读取文件类型的目录
  341. int myftyper(struct copypath *pp,struct threadpool *pool,char *ftype)
  342. {
  343. DIR *dirp=opendir(pp->oldpath);
  344. if(dirp==NULL)
  345. {
  346. perror("失败:\n");
  347. return -1;
  348. }
  349. struct dirent *p;
  350. while((p=readdir(dirp))!=NULL)
  351. {
  352. if(p->d_type==DT_REG) //普通文件
  353. {
  354. if(strstr(p->d_name,ftype)!=NULL)
  355. {
  356. struct copypath *mypath=malloc(sizeof(struct copypath));
  357. sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  358. sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
  359. add_task(myregcp,mypath,pool); //实现
  360. }
  361. }
  362. if(p->d_type==DT_DIR) //文件夹
  363. {
  364. if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
  365. {
  366. struct copypath *mydirpath=malloc(sizeof(struct copypath));
  367. sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  368. sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
  369. mkdir(mydirpath->newpath,0777);
  370. myftyper(mydirpath,pool,ftype);
  371. }
  372. }
  373. }
  374. closedir(dirp);
  375. return 1;
  376. }
  377. //树实现
  378. void dirtree(char dirpath[],int level)
  379. {
  380. int i;
  381. char *dirname=NULL;
  382. int dirlen;
  383. DIR *dp=opendir(dirpath);
  384. if(dp==NULL)
  385. {
  386. perror("失败:\n");
  387. return;
  388. }
  389. struct dirent *ep;
  390. while((ep=readdir(dp))!=NULL)
  391. {
  392. if(strncmp(ep->d_name, ".", 1) == 0)
  393. continue;
  394. for(i=0;i<level;i++)
  395. {
  396. printf("|");
  397. printf(" ");
  398. }
  399. printf("|--- ");
  400. printf("\033[1;32;40m %s \033[0m\n",ep->d_name);
  401. if(ep->d_type==DT_DIR)
  402. {
  403. //当前目录长度
  404. dirlen=strlen(dirpath)+1;
  405. //备份
  406. dirname=(char *)malloc(dirlen);
  407. memset(dirname,0,dirlen);
  408. memcpy(dirname,dirpath,dirlen);
  409.  
  410. strcat(dirpath,"/");
  411. strcat(dirpath,ep->d_name);
  412. dirtree(dirpath,level+1); //递归实现树效果
  413. //恢复之前的目录名
  414. memcpy(dirpath,dirname,dirlen);
  415. free(dirname);
  416. dirname = NULL;
  417. }
  418. }
  419. closedir(dp);
  420. }
  421.  
  422. //递归查找相似文件-查找文件
  423. int sc_file(struct copypath *pp,char *filename)
  424. {
  425. DIR *dirp=opendir(pp->oldpath);
  426. if(dirp==NULL)
  427. {
  428. perror("失败:\n");
  429. return -1;
  430. }
  431. struct dirent *p;
  432. while((p=readdir(dirp))!=NULL)
  433. {
  434. if(p->d_type==DT_REG) //普通文件
  435. {
  436. if(strstr(p->d_name,filename)!=NULL) //文件类型
  437. {
  438. struct copypath *mypath=malloc(sizeof(struct copypath));
  439. sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  440. printf("已找到文件路径:%s\n",mypath->oldpath);
  441. free(mypath);
  442. }
  443. }
  444. if(p->d_type==DT_DIR) //文件夹
  445. {
  446. if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
  447. {
  448. if(strstr(p->d_name,filename)!=NULL) //文件类型
  449. {
  450. struct copypath *mypath1=malloc(sizeof(struct copypath));
  451. sprintf(mypath1->oldpath,"%s/%s",pp->oldpath,p->d_name);
  452. printf("已找到文件路径:%s\n",mypath1->oldpath);
  453. free(mypath1);
  454. }
  455. struct copypath *mydirpath=malloc(sizeof(struct copypath));
  456. sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  457. sc_file(mydirpath,filename);
  458. }
  459. }
  460. }
  461. closedir(dirp);
  462. return 1;
  463. }
  464. //删除--文件\文件夹
  465. int alldet(struct copypath *pp)
  466. {
  467. DIR *dirp=opendir(pp->oldpath);
  468. struct dirent *p;
  469. while((p=readdir(dirp))!=NULL)
  470. {
  471. if(p->d_type==DT_REG) //普通文件
  472. {
  473. struct copypath *mypath=malloc(sizeof(struct copypath));
  474. sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  475. remove(mypath->oldpath);
  476. }
  477. if(p->d_type==DT_DIR) //文件夹
  478. {
  479. if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
  480. {
  481. struct copypath *mydirpath=malloc(sizeof(struct copypath));
  482. sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
  483. alldet(mydirpath);
  484. rmdir(mydirpath->oldpath);
  485. }
  486. }
  487. }
  488. closedir(dirp);
  489. rmdir((pp->oldpath));
  490. return 1;
  491. }
  492. /***************************************************************************/
  493.  
  494. /***************************************************************************/
  495. // 简化主程序
  496. /***************************************************************************/
  497. int simcopy_all(struct threadpool *mypool) //简化主程序--复制全部
  498. {
  499. tm=s=cs=0;
  500. struct copypath paths; //新旧路径结构体
  501. printf("请输入源文件\n");
  502. scanf("%s",paths.oldpath);
  503. printf("请输入目标文件\n");
  504. scanf("%s",paths.newpath);
  505. mycopyname(&paths);
  506. sprintf(paths.newpath,"%s/%s",paths.newpath,paths.target);
  507. mkdir(paths.newpath,0777);
  508. size_sum(&paths); //计算字节数
  509. usleep(20);
  510. printf("总字节数:%ld\n",s);
  511. add_task(my_time,NULL,mypool);
  512. add_task(pro_bar,NULL,mypool);
  513. myreaddir(&paths,mypool);
  514. }
  515. void simcopy(struct threadpool *mypool) //简化主程序--按文件类型复制
  516. {
  517. tm=s=cs=0;
  518. char ftype[6]; //文件类型变量
  519. struct copypath paths;
  520. printf("请输入源文件\n");
  521. scanf("%s",paths.oldpath);
  522. printf("请输入目标文件\n");
  523. scanf("%s",paths.newpath);
  524. mycopyname(&paths);
  525. sprintf(paths.newpath,"%s/%s",paths.newpath,paths.target);
  526. mkdir(paths.newpath,0777);
  527. printf("请输入要复制的文件类型,如.txt等\n");
  528. scanf("%s",ftype);
  529. ftypesize_sum(&paths,ftype);
  530. printf("总字节数:%ld\n",s);
  531. usleep(20);
  532. add_task(my_time,NULL,mypool);
  533. add_task(pro_bar,NULL,mypool);
  534. myftyper(&paths,mypool,ftype);
  535. }
  536. void simtree() //简化主程序--文件树
  537. {
  538. char direntName[256];
  539. struct copypath paths;
  540. printf("请输入源文件\n");
  541. scanf("%s",paths.oldpath);
  542. memset(direntName, 0, sizeof(direntName));
  543. strcat(direntName, paths.oldpath);
  544. printf("%s\n",paths.oldpath);
  545. dirtree(direntName, 0);
  546. }
  547. void myscfile() //简化主程序--查找
  548. {
  549. char fname[256];
  550. struct copypath paths;
  551. printf("请输入查找文件夹名\n");
  552. scanf("%s",paths.oldpath);
  553. printf("请输入要查找的文件名\n");
  554. scanf("%s",fname);
  555. sc_file(&paths,fname);
  556. usleep(10);
  557. }
  558. void mydel() //简化主程序--删除
  559. {
  560. tm=s=cs=0;
  561. char delfile[100];
  562. struct copypath paths;
  563. printf("请输入要删除的文件夹\n");
  564. scanf("%s",paths.oldpath);
  565. size_sum(&paths); //计算字节数
  566. printf("size is: %ld\n",s);
  567. alldet(&paths);
  568. usleep(10);
  569. }
  570. void endshow() //简化主程序--结束
  571. {
  572. printf("请输入 \n");
  573. printf(" 1--继续 \n");
  574. printf(" 2--退出 \n");
  575. scanf("%d",&flag);
  576. }
  577. /***************************************************************************/
  578. //销毁线程池
  579. int pool_destroy(struct threadpool *pool)
  580. {
  581. int i;
  582. //改变标志位,让线程退出死循环
  583. pool->threadflag=false;
  584. //唤醒所有线程
  585. pthread_cond_broadcast(&(pool->threadcond));
  586. //回收所有线程
  587. for(i=0;i<pool->threadnum;i++)
  588. {
  589. pthread_join(pool->threadid[i],NULL);
  590. //printf("%ld线程已被回收\n",pool->threadid[i]);
  591. }
  592. return 0;
  593. }
  594.  
  595. int main()
  596. {
  597. struct copypath paths;
  598. while(1)
  599. {
  600. flag=0;
  601. system("clear");
  602. myhead=task_init(); //初始化任务链表的表头
  603. struct threadpool *mypool=thread_init(10); //创建并初始化线程池
  604. int ret=showdow();
  605. switch(ret)
  606. {
  607. case 1: //拷贝全部
  608. simcopy_all(mypool);
  609. pool_destroy(mypool); //线程池的销毁
  610. printf("拷贝花费:%d seconds\n",tm);
  611. break;
  612. case 2: //拷贝部分
  613. simcopy(mypool);
  614. pool_destroy(mypool);
  615. printf("拷贝花费:%d seconds\n",tm);
  616. break;
  617. case 3: //显示文件树
  618. simtree();
  619. break;
  620. case 4: //查找某个文件--显示相似的文件
  621. myscfile();
  622. break;
  623. case 5: //删除某个文件夹
  624. mydel();
  625. printf("delete done\n");
  626. break;
  627. default:
  628. break;
  629. }
  630. endshow();
  631. if(flag==1)
  632. continue;
  633. else if(flag==2)
  634. break;
  635. }
  636. system("clear");
  637. usleep(20);
  638. return 0;
  639. }

码源:

http://pan-yz.chaoxing.com/share/info/b54be58ad063e1e9

有什么建议,欢迎联系。邮箱:2460576606@qq.com

基于linux与线程池实现文件管理的更多相关文章

  1. 开源项目SMSS开发指南(二)——基于libevent的线程池

    libevent是一套轻量级的网络库,基于事件驱动开发.能够实现多线程的多路复用和注册事件响应.本文将介绍libevent的基本功能以及如何利用libevent开发一个线程池. 一. 使用指南 监听服 ...

  2. linux C 线程池(物不可穷也~)

    Linux 多线程编程之 线程池 的原理和一个简单的C实现,提高对多线程编 程的认知,同步处理等操作,以及如何在实际项目中高效的利用多线程开 发. 1.  线程池介绍 为什么需要线程池??? 目前的大 ...

  3. Linux pthread 线程池实现

    基于pthread封装了一个简易的ThreadPool,具有以下特性: 1.具有优先级的任务队列 2.线程池大小可以二次调整,增加线程或者删除空闲线程 3.任务两种重写方式,重写run或者使用函数回调 ...

  4. Linux C++线程池实例

    想做一个多线程服务器测试程序,因此参考了github的一些实例,然后自己动手写了类似的代码来加深理解. 目前了解的线程池实现有2种思路: 第一种: 主进程创建一定数量的线程,并将其全部挂起,此时线程状 ...

  5. 基于hystrix的线程池隔离

    hystrix进行资源隔离,其实是提供了一个抽象,叫做command,就是说,你如果要把对某一个依赖服务的所有调用请求,全部隔离在同一份资源池内 对这个依赖服务的所有调用请求,全部走这个资源池内的资源 ...

  6. Linux C++线程池

    .为什么需要线程池? 部分应用程序需要执行很多细小的任务,对于每个任务都创建一个线程来完成,任务完成后销毁线程,而这就会产生一个问题:当执行的任务所需要的时间T1小于等于创建线程时间T2和销毁线程时间 ...

  7. Linux下线程池的理解与简单实现

    首先,线程池是什么?顾名思义,就是把一堆开辟好的线程放在一个池子里统一管理,就是一个线程池. 其次,为什么要用线程池,难道来一个请求给它申请一个线程,请求处理完了释放线程不行么?也行,但是如果创建线程 ...

  8. 基于C++11线程池

    1.包装线程对象 class task : public std::tr1::enable_shared_from_this<task> { public: task():exit_(fa ...

  9. Linux简单线程池实现(带源码)

    这里给个线程池的实现代码,里面带有个应用小例子,方便学习使用,代码 GCC 编译可用.参照代码看下面介绍的线程池原理跟容易接受,百度云下载链接: http://pan.baidu.com/s/1i3z ...

随机推荐

  1. Stream之高级函数

    上回文说到了有关Stream一些数学函数的用法.今天来说下Stream一些高级的函数用法,这些函数在日常工作中也是必不可少的,测试数据还是引用上一篇的数据. Map 这个方法我个人称之为转换函数,把一 ...

  2. Tomcat 源码环境搭建

    Tomcat 源码搭建 下载源码 下载地址 :https://tomcat.apache.org/download-80.cgi#8.5.35 下载之后解压缩 导入Idea 添加pom.xml文件 & ...

  3. C 标准库函数手册摘要

    <stdlib.h> int abs( int value ); long int labs( long int value ); 返回参数的绝对值 int rand( void ); v ...

  4. Java(18)抽象类

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201625.html 博客主页:https://www.cnblogs.com/testero ...

  5. /usr/bin/python^M: bad interpreter: No such file or directory

    利用如下命令查看文件格式 :set ff 或 :set fileformat 可以看到如下信息 fileformat=dos 或 fileformat=unix 利用如下命令修改文件格式 :set f ...

  6. 【UE4】虚幻引擎技术直播汇总(含中英文直播)

    B站虚幻引擎官方账号 中文直播 [中文直播]第35期 | 使用GIS在UE中创造真实地球风貌 | Epic 周澄清 [中文直播]第34期 | 包教包会的Epic MegaGrants申请之道 | Ep ...

  7. 示波器分析I2C时序波形图

    对于嵌入式开发的朋友来说,I2C协议实在是再熟悉不过了,有太多的器件,采用的都是通过I2C来进行相应的设置.今天,我们就随便聊聊这个I2C协议. I2C协议中最重要的一点是I2C地址.这个地址有7位和 ...

  8. 从零开始的DIY智能家居 - 基于 ESP32 的土壤湿度传感器

    前言 自从上次做了那个 甲醛传感器 和 水浊度传感器 之后开始尝到智能家居的甜头了,这两东西有没有用我不知道,但是没事的时候掏出手机瞄两眼,看着就让人很安心( ̄︶ ̄). 于是懒惰的我开始琢磨把给植物浇 ...

  9. Android编译执行envsetup.sh,产生工具命令m、mm、mmm、mmma、tapas 、croot、cgrep、jgrep、 resgrep、godir

    一般来说编译一个sdk或者一个比较大的工程项目,第一步都是执行 envsetup.sh这个脚本,比如编译android,qt源码以及其他一些嵌入式的sdk. 而且执行的时候需要特别注意使用 sourc ...

  10. 原串反转 牛客网 程序员面试金典 C++ Python

    原串反转 牛客网 程序员面试金典 C++ Python 题目描述 请实现一个算法,在不使用额外数据结构和储存空间的情况下,翻转一个给定的字符串(可以使用单个过程变量). 给定一个string iniS ...