多线程复制文件

#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#define _CRT_SECURE_NO_WARNINGS

using namespace std;
CRITICAL_SECTION g_csThreadCode;
volatile long g_nNum; //全局资源

struct ThreadInfo
{
	int i;
	int flen;		//fLen
	int blocklen;	//blockLen
	FILE* a;		//fsrc
	FILE* b;		//ftmp
	int threadnum;	//N

}Info;

DWORD WINAPI Fun(void* pPM)
{
	//由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来
	//int nThreadNum = *(int *)pPM; //子线程获取参数
	
	
	EnterCriticalSection(&g_csThreadCode);
	//InterlockedIncrement(&g_nNum);      // 全局变量
	//Sleep(0);
	printf("第 %d个线程正在执行!\n", g_nNum+1);
	//写入文件
	int offset = g_nNum*Info.blocklen;		//i*blockLen; //计算偏移量 
	fseek(Info.a, offset, SEEK_SET);
	fseek(Info.b, offset, SEEK_SET);		
	int count = 0;  //统计写入ftmp的数量
	if (g_nNum == Info.threadnum - 1)
		Info.blocklen = Info.flen - Info.blocklen*(Info.threadnum - 1);  //最后一块的长度
	while (count<Info.blocklen && !feof(Info.a))
	{
		fputc(fgetc(Info.a), Info.b);
		count++;
	}
	//写入结束

	g_nNum++;
	LeaveCriticalSection(&g_csThreadCode);
	return 0;
}

int main()
{
	g_nNum = 0;
	int THREAD_NUM; //子线程个数
	printf("请输入线程数:\n");
	cin >> THREAD_NUM;
	
	//打开要复制的文件
	FILE *fsrc = fopen("D:\\document\\123.mp4", "rb");  // 源文件
	fseek(fsrc, 0, SEEK_END);
	int fLen = ftell(fsrc);  // 文件长度
	printf("文件长度:%d\n", fLen);
	int blockLen = fLen / THREAD_NUM;   // 每一块的长度
	printf("blockLen:%d\n", blockLen);
	//创建大小相同的文件
	FILE *ftmp;  // 临时文件,
	char tName[20];
	char tdir[60] = "D:\\document\\";
	sprintf(tName, "new123.mp4");//生成文件名
	strcat(tdir, tName);  //产生临时目录
	ftmp = fopen(tdir, "wb");  // 生成临时文件
	fseek(ftmp, fLen - 1, 0);//指定大小
	fputc(0, ftmp);
	HANDLE  handle[MAX_PATH];
	InitializeCriticalSection(&g_csThreadCode);
	int i = 0;
	
	Info.a = fsrc;
	Info.b = ftmp;
	Info.blocklen = blockLen;
	Info.flen = fLen;
	Info.threadnum = THREAD_NUM;


	while (i < THREAD_NUM)
	{
		//等子线程接收到参数时主线程可能改变了这个i的值
		handle[i] = CreateThread(NULL, 0, Fun, &Info, 0, NULL); 
		i++;
	}

	//保证子线程已全部运行结束
	WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
	DeleteCriticalSection(&g_csThreadCode);
	system("pause");
	return 0;
}

// MultipleTask.cpp: 定义控制台应用程序的入口点。
//	每个下载是单独的一个线程

#include "stdafx.h"
#include "DownloadInfo.h"
#include <sstream>

//解除最多等待64个线程限制
DWORD SyncWaitForMultipleObjs(HANDLE * handles, int count)
{
	int waitingThreadsCount = count;
	int index = 0;
	DWORD res = 0;
	while (waitingThreadsCount >= MAXIMUM_WAIT_OBJECTS)
	{
		res = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, &handles[index], TRUE, INFINITE);
		if (res == WAIT_TIMEOUT || res == WAIT_FAILED)
		{
			puts("1. Wait Failed.");
			return res;
		}

		waitingThreadsCount -= MAXIMUM_WAIT_OBJECTS;
		index += MAXIMUM_WAIT_OBJECTS;
	}

	if (waitingThreadsCount > 0)
	{
		res = WaitForMultipleObjects(waitingThreadsCount, &handles[index], TRUE, INFINITE);
		if (res == WAIT_TIMEOUT || res == WAIT_FAILED)
		{
			puts("2. Wait Failed.");
		}
	}

	return res;
}
LPWSTR MtoW(char* temp, LPTSTR buffera) {

	DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, temp, -1, NULL, 0);
	//计算这个GB2312实际有几个字组成

	wchar_t* pwText;
	pwText = new wchar_t[dwNum];
	if (!pwText)
	{
		delete[]pwText;
	}
	MultiByteToWideChar(CP_ACP, 0, temp, -1, pwText, dwNum);
	//把GB2312变成UNICODE
	wcscpy_s(buffera, MAX_PATH, pwText);
	delete[]pwText;
	return buffera;
}
bool InternetDownload(const string &URL, const string &FN)
{
	CString strURL, strFN;
	strURL = URL.c_str();
	strFN = FN.c_str();
	CInternetSession internetSession(L"DownloaderWsl",
		1,
		PRE_CONFIG_INTERNET_ACCESS,
		NULL,
		NULL,
		0);

	BOOL bSucceed = TRUE;

	try
	{


		// 统一以二进制方式下载
		DWORD       dwFlag = INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD;
		//子类对基类进行了强制类型转换,利用函数打开要下载的网址链接 wangsl
		//将要下载文件的信息
		CHttpFile   * pF = (CHttpFile*)internetSession.OpenURL(strURL, 1, dwFlag);

		// 得到文件大小
		CString      str;
		pF->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, str);
		int   nFileSize = _ttoi(str);	//文件大小,将字符串转换成整形
										//int nTotalSize = nFileSize;

		if (pF != NULL)
		{

			//创建下载文件,不存在就创建,存在就直接写入 wangsl
			CFile cf;
			if (!cf.Open(strFN, CFile::modeCreate | CFile::modeWrite, NULL))
			{
				return FALSE;
			}
			//
			BYTE Buffer[8192];
			//为Buffer分配空间 wangsl
			ZeroMemory(Buffer, sizeof(Buffer));
			int nReadLen = 0;

			while ((nReadLen = pF->Read(Buffer, sizeof(Buffer))) > 0)	//每次读取固定长度到Buffer中,返回实际读取的长度 wangsl
			{

				cf.Write(Buffer, nReadLen);	//在创建的文件中写入读取的内容 wangsl

				nFileSize -= nReadLen;
				TRACE("剩余:%d\n", nFileSize);
			}

			cf.Close();
			pF->Close();

			delete pF;

		}
	}
	catch (CInternetException& e)
	{
		char szBuffer[128];
		ZeroMemory(szBuffer, sizeof(szBuffer));
		LPTSTR buffer = NULL;
		MtoW(szBuffer, buffer);
		e.GetErrorMessage(buffer, sizeof(buffer), NULL);
		TRACE("InternetDownload, Exception: %s ", buffer);
	}
	catch (...)
	{
		TRACE("InternetDownload, Exception: ... ");
	}
	internetSession.Close();


	if (!bSucceed)
		DeleteFile(strFN);
	return bSucceed;
}

unsigned int __stdcall Fun(void *pPM)
{
	Info nThreadNum = *(Info *)pPM;
	InternetDownload(nThreadNum.url, nThreadNum.filename);
	return 0;
}





int main()
{
	//接收网址数据
	int n = 0;
	cout << "请输入要下载的任务数:" << endl;
	cin >> n;
	cout << "请输入任务的URL:" << endl;
	for (int k = 0; k < n ; k++)
	{
		cin >> FN1[k].url;
	}
	
	//接收完毕 创建线程
	HANDLE  handle[MAX_PATH];
	int i = 0;
	while (i < n)
	{
		int nNum = GetTickCount();
		char szFilePath[MAX_PATH] = { 0 };
		sprintf(szFilePath, "%d%s", nNum, FILE_TYPE);
		FN1[i].filename = szFilePath;
		handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &FN1[i], 0, NULL);
		Sleep(5);
		i++;
	}
	SyncWaitForMultipleObjs(handle, n);

	
	for (i = 0; i < n; i++)
		CloseHandle(handle[i]);
	system("pause");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值