多线程相关操作(五)实例

       以下代码实现目录复制(linux 系统下), 依赖于 pthread 库(第一版本)

代码错误:stat 函数无法获取文件夹大小

                   应该递归将文件复制放入任务当中

                   总结,以上代码不仅有错误,而且还没有使用到线程池,思路不清晰。

             

#include "pthpool.h"
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>



// 原始路径
struct dir
{
	char scr[255];
	char dst[255];
	char *name;
	thread_pool *pool;
};

// 文件名----绝对路径
struct name
{
	char src_name[255];
	char dst_name[255];	
};

// 字符串拼接 
char *linkchar(char *src, char *name)
{
	char *ret = calloc(1, 255);
	int i, j;
	
	for (i = 0; src[i] != '\0'; i++);
	src[i] = '/';
	i++;
	for (j = 0; name[j] != '\0'; j++)
	{
		src[i] = name[j];
		i++;
	}
	src[i] = '\0';
	strcpy(ret, src);
	
	return ret;
}

// 线程任务,进行文件拷贝,参数文件属性
void *copyreg(void *arg)
{
	struct name *copyfile = (struct name *)arg;
	
//	printf("src_path: %s\n", copyfile->src_name);
	FILE *fp1 = fopen(copyfile->src_name, "r");
	if (fp1 == NULL)
	{
		perror("打开源文件失败");
		exit(1);
	}

//	printf("dst_path: %s\n", copyfile->dst_name);
	FILE *fp2 = fopen(copyfile->dst_name, "w");

	if (fp2 == NULL)
	{
		perror("打开目标文件失败");
		exit(1);
	}


	char *buf = calloc(100, 1);
	while(1)
	{
		long a = ftell(fp1);
		if ( ! (fread(buf, 100, 1, fp1)) )
		{
			long b = ftell(fp1);
			fwrite(buf, b-a, 1, fp2);
			break;
		}
		fwrite(buf, 100, 1, fp2);
	
	}

	free(buf);
	free(copyfile);
	fclose(fp1);
	fclose(fp2);
	return NULL;
}

// 递归获取目录文件名
void mycopy(thread_pool *pool, char *src, char *dst)
{
	mkdir(dst, 0777);
	DIR *dp = opendir(src);	
	struct dirent *ep;
	char stmp[255];
	char dtmp[255];
	strcpy(stmp, src);
	strcpy(dtmp, dst);
		
	while (1)
	{	
	
		strcpy(src, stmp);
		strcpy(dst, dtmp);
		ep = readdir(dp);
		if (ep == NULL)
			break;
		if(ep->d_name[0] == '.')
			continue;
				
		src = linkchar(src, ep->d_name);
		dst = linkchar(dst, ep->d_name);
		

			
		struct stat info1;
		bzero(&info1, sizeof (info1));
		stat(src, &info1);
			
		if (S_ISREG(info1.st_mode))
		{
			struct name *copy1 = calloc(1, sizeof (struct name));		
			strcpy(copy1->src_name, src);
			strcpy(copy1->dst_name, dst);

			add_task(pool, copyreg, copy1);
			
		}
		else if (S_ISDIR(info1.st_mode))
		{
			mycopy(pool, src, dst);
		}	
	}
	
}

// 获取文件属性 
void copydir(thread_pool *pool, char *src, char *dst)
{
	struct stat info;
	bzero(&info, sizeof (info));
	stat(src, &info);
	
	// 复制的本身就是文件	
	if (S_ISREG(info.st_mode))
	{
		struct name *copy = calloc(1, sizeof (struct name));
		strcpy(copy->src_name, src);


		strcpy(copy->dst_name, dst);

		add_task(pool, copyreg, copy);
	}
	// 复制的是目录 
	else if (S_ISDIR(info.st_mode))
	{
		mycopy(pool, src, dst);
	}
}





 // 获取复制路径双方的详细信息 
void getdir(struct dir *mydir, char *argv1, char *argv2)
{
	bzero(mydir, sizeof (struct dir));
	// 判断是绝对路径还是相对路径
	
	if (argv1[0] == '/')
	{
		strcpy(mydir->scr, argv1);
	}
	else
	{
		char scr_path[255];	          //源路径
		getcwd(scr_path, 255);
		char *scr = linkchar(scr_path, argv1);
		strcpy(mydir->scr, scr);
		//printf("scr_path: %s\n", scr);
	} 
	
	if (argv2[0] == '/')
	{
		strcpy(mydir->dst ,argv2);
	}
	else
	{
		char dst_path[255];	          //目标路径
		getcwd(dst_path, 255);
		char *dst = linkchar(dst_path, argv2);
		strcpy(mydir->dst, dst);
		//printf("dst_path: %s\n", dst);
	}
}

// 用于主线程计算拷贝目录的时间
void timenum(char *srcname, char *dstname)
{
	struct stat srcinfo;
	bzero(&srcinfo, sizeof (srcinfo));
	stat(srcname, &srcinfo);
	printf("from %s to %s\n", srcname, dstname);	
	struct stat dstinfo;
	bzero(&dstinfo, sizeof (dstinfo));

	
	long m = srcinfo.st_size;
	printf("src_file size: %ld\n", m);

	for (int k = 0; k <= 100; k += 10)
	{
		printf("%d%c\t", k, '%');
	}
	printf("\n");
	long n;
	int i = 0;
	int j = 0;
	int menu = 0;
	int tmp = 0;
	if (m != 0)
	{

		while (1)
		{
			usleep(10000);
			stat(dstname, &dstinfo);
			n = dstinfo.st_size*10;

			for (menu = 0; menu < (n/m-tmp); menu++)
			{
				printf(">>>>>>>>");
				fflush(stdout);
			}
			tmp = n/m;
			if (tmp == 10)
				break;		
			i++;
		} 
	}
	else
	{
		for(j = 0; j < 10; j++)
		{
			printf(">>>>>>>>");
			fflush(stdout);
		}		
	}

	if (i == 0)
		i = 1;
	printf("\nsuccess...\n");
	printf("use time: %dms\n", i*10);
}

int main(int argc, char **argv)
{
	printf("begining...\n");
	struct dir mydir;
	if (argc != 3)
	{
		printf("use: %s src_filename dis_filename\n", argv[0]);
		return 0;	
	}
	
	getdir(&mydir, argv[1], argv[2]);
	// 一、初始化一个带有 20 条线程的线程池
	mydir.pool = calloc(1, sizeof (thread_pool));
	init_pool(mydir.pool, 20);
		
	char srcname[255];
	char dstname[255];
	strcpy(srcname, mydir.scr);
	strcpy(dstname, mydir.dst);
	//二、递归的复制目录
	copydir(mydir.pool, mydir.scr, mydir.dst);
	
	// 计时 和 进度条显示 
	timenum(srcname, dstname);
	// 销毁线程池
	destroy_pool(mydir.pool);
	return 0; 
	
} 




猜你喜欢

转载自blog.csdn.net/qq_41985711/article/details/82658668
今日推荐