⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filecutter.cpp

📁 VC源码:文件分割器 VC源码:文件分割器
💻 CPP
字号:
/////////////////////////////////////////////////////
// FileCutter.cpp文件

#include "FileCutter.h"


// 内部工作线程
UINT _CutterEntry(LPVOID lpParam)
{
	// 得到CFileCutter对象的指针
	CFileCutter* pCutter = (CFileCutter*)lpParam;

	// 循环处理用户的工作请求
	while(::WaitForSingleObject(pCutter->m_hWorkEvent, INFINITE) == WAIT_OBJECT_0 && 
									!pCutter->m_bExitThread)
	{
		// 设置状态标志,说明正在工作
		::EnterCriticalSection(&pCutter->m_cs);
		pCutter->m_bRunning = TRUE;
		::LeaveCriticalSection(&pCutter->m_cs);

		// 开始真正的工作
		if(pCutter->m_bSplit)
			pCutter->DoSplit();
		else
			pCutter->DoMerge();

		// 准备接受新的工作任务
		pCutter->Reset();
	}

	return 0;
}

//-----------------------接口成员------------------------//

CFileCutter::CFileCutter(HWND hWndNotify) 
{
	// 初始化全局有效变量

	m_hWndNotify = hWndNotify;
	m_bExitThread = FALSE;
	m_bSuspend = FALSE;
	// 创建等待事件对象
	m_hWorkEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	// 创建工作线程
	m_pThread = AfxBeginThread(_CutterEntry, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL);
	m_pThread->m_bAutoDelete = FALSE;
	m_pThread->ResumeThread();

	// 初始化工作期间有效变量

	// 创建关键代码段
	::InitializeCriticalSection(&m_cs);	
	Reset(); 
}

void CFileCutter::Reset()
{
	::EnterCriticalSection(&m_cs);
	
	// 重置参数信息
	m_strSource.Empty();
	m_strDest.Empty();
	m_uFileSize = 0;
	m_bSplit = TRUE;

	// 重置状态标志
	m_bContinue = TRUE;
	m_bRunning = FALSE;
	
	::LeaveCriticalSection(&m_cs);
}

CFileCutter::~CFileCutter()
{
	// 设置结束标志
	m_bExitThread = TRUE;

	// 设置强制退出标志
	::EnterCriticalSection(&m_cs);
	m_bContinue = FALSE;
	::LeaveCriticalSection(&m_cs);

	// 防止线程在m_hWorkEvent事件上等待
	::SetEvent(m_hWorkEvent);

	// 确保工作线程结束
	::WaitForSingleObject(m_pThread->m_hThread, INFINITE);
	
	// 释放所有资源
	::CloseHandle(m_hWorkEvent);
	::DeleteCriticalSection(&m_cs); 
	delete m_pThread;
}

BOOL CFileCutter::StartSplit(LPCTSTR lpszDestDir, LPCTSTR lpszSourceFile, UINT uFileSize)
{
	if(m_bRunning)
		return FALSE;

	// 保存参数
	::EnterCriticalSection(&m_cs);
	m_strSource = lpszSourceFile; 
	m_strDest = lpszDestDir;
	m_uFileSize = uFileSize;
	m_bSplit = TRUE;
	::LeaveCriticalSection(&m_cs);

	// 通知线程开始工作
	::SetEvent(m_hWorkEvent);
	return TRUE;
}

BOOL CFileCutter::StartMerge(LPCTSTR lpszDestFile, LPCTSTR lpszSourceDir)
{
	if(m_bRunning)
		return FALSE;

	// 保存参数
	::EnterCriticalSection(&m_cs);
	m_strSource = lpszSourceDir; 
	m_strDest = lpszDestFile;
	m_bSplit = FALSE;
	::LeaveCriticalSection(&m_cs);

	// 通知线程开始工作
	::SetEvent(m_hWorkEvent);
	return TRUE;
}

BOOL CFileCutter::SuspendCutter()
{
	if(!m_bRunning)
		return FALSE;

	// 暂停工作线程
	if(!m_bSuspend)
	{
		m_pThread->SuspendThread();
		m_bSuspend = TRUE;
	}
	return TRUE;
}

BOOL CFileCutter::ResumeCutter()
{
	if(!m_bRunning)
		return FALSE;

	// 唤醒工作线程
	if(m_bSuspend)
	{
		m_pThread->ResumeThread();
		m_bSuspend = FALSE;
	}
	return TRUE;
}

void CFileCutter::StopCutter()
{
	// 设置强制退出标志
	::EnterCriticalSection(&m_cs);
	m_bContinue = FALSE;
	::LeaveCriticalSection(&m_cs);

	// 防止线程处于暂停状态
	ResumeCutter();
}

//-------------------------实现代码-------------------------//


void CFileCutter::DoSplit()
{
	int nCompleted = 0;
	CString strSourceFile = m_strSource;
	CString strDestDir = m_strDest;
	CFile sourceFile, destFile;
	
	// 打开源文件
	BOOL bOK = sourceFile.Open(strSourceFile,
		CFile::modeRead|CFile::shareDenyWrite|CFile::typeBinary);
	if(!bOK)
	{
		// 通知用户,源文件出错
		::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitSourceErr, nCompleted);
		return;
	}

	// 确保目标目录存在(逐层创建它们)
	int nPos = -1;
	while((nPos = strDestDir.Find('\\', nPos+1)) != -1)
	{
		::CreateDirectory(strDestDir.Left(nPos), NULL);
	} 
	::CreateDirectory(strDestDir, NULL);
	if(strDestDir.Right(1) != '\\')
		strDestDir += '\\';

	// 通知用户,开始分割文件
	int nTotalFiles = sourceFile.GetLength()/m_uFileSize + 1;
	::PostMessage(m_hWndNotify, WM_CUTTERSTART, nTotalFiles, TRUE);
	
	// 开始去读源文件,将数据写入目标文件
	const int c_page = 4*1024;
	char buff[c_page];
	DWORD dwRead;

	CString sDestName;
	int nPreCount = 1;
	UINT uWriteBytes;
	do
	{
		// 创建一个目标文件
		sDestName.Format("%d__", nPreCount);
		sDestName += sourceFile.GetFileName();
		if(!destFile.Open(strDestDir + sDestName, CFile::modeWrite|CFile::modeCreate))
		{
			::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitDestErr, nCompleted);
			sourceFile.Close();
			return;
		}

		// 向目标文件写数据,直到大小符合用户的要求,或者源文件读完
		uWriteBytes = 0;
		do
		{
			// 首先判断是否要求终止执行
			if(!m_bContinue)
			{
				destFile.Close();
				sourceFile.Close();
				if(!m_bExitThread)
					::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitUserForce, nCompleted);
				return;
			}

			// 进行真正的读写操作
			dwRead = sourceFile.Read(buff, c_page);
			destFile.Write(buff, dwRead);
			uWriteBytes += dwRead;
		}while(dwRead > 0 && uWriteBytes < m_uFileSize);

		// 关闭这个目标文件
		destFile.Close();

		// 通知用户,当前的状态信息
		nCompleted = nPreCount++;
		::PostMessage(m_hWndNotify, WM_CUTTERSTATUS, 0, nCompleted);
	}while(dwRead > 0);

	// 关闭源文件
	sourceFile.Close();

	// 通知用户,工作完成
	::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitSuccess, nCompleted);
}


void CFileCutter::DoMerge()
{
	int nCompleted = 0;
	CString strSourceDir = m_strSource;
	CString strDestFile = m_strDest;
	if(strSourceDir.Right(1) != '\\')
		strSourceDir += '\\';
	if(strDestFile.Right(1) != '\\')
		strDestFile += '\\';
	
	// 取得源目录中待合并的文件的文件名称和数量
	CString strFileName;
	int nTotalFiles = 0;
	CFileFind find;
	BOOL bRet;
	if(find.FindFile(strSourceDir + "*.*"))
	{
		do
		{
			bRet = find.FindNextFile();
			if(find.IsDirectory() && find.IsDots())
				continue;
			if(find.GetFileName().Find("__", 0) != -1)
			{
				nTotalFiles++;
				strFileName = find.GetFileName();
			}
		}while(bRet);
	}
	find.Close();

	if(nTotalFiles == 0)
	{
		// 通知用户,源文件出错
		::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitSourceErr, nCompleted);
		return;
	}

	// 取得文件名称
	strFileName = strFileName.Mid(strFileName.Find("__") + 2);

	// 确保目标目录存在(逐层创建它们)
	int nPos = 0;
	while((nPos = strDestFile.Find('\\', nPos+1)) != -1)
	{
		::CreateDirectory(strDestFile.Left(nPos + 1), NULL);
	}
	::CreateDirectory(strDestFile, NULL);
	
	// 创建目标文件
	CFile sourceFile, destFile;
	strDestFile += strFileName;
	if(!destFile.Open(strDestFile, CFile::modeRead|CFile::modeWrite|CFile::modeCreate))
	{
		::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitDestErr, nCompleted);
		return;
	}

	// 通知用户,开始分割文件
	::PostMessage(m_hWndNotify, WM_CUTTERSTART, nTotalFiles, nCompleted);	

	// 开始去读源文件,将数据写入目标文件
	const int c_page = 4*1024;
	char buff[c_page];
	int nPreCount = 1;
	CString sSourceName;
	DWORD dwRead;
	do
	{
		// 打开一个源文件
		sSourceName.Format("%d__", nPreCount);
		sSourceName += strFileName;
		if(!sourceFile.Open(strSourceDir + sSourceName, CFile::modeRead|CFile::shareDenyWrite))
		{
			break;
		}

		// 将这个源文件中的数据全部写入目标文件
		do
		{
			if(!m_bContinue)
			{
				sourceFile.Close();
				destFile.Close();
				if(!m_bExitThread)
					::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitUserForce, nCompleted);
				return;
			}
			dwRead = sourceFile.Read(buff, c_page);
			destFile.Write(buff, dwRead);
		}
		while(dwRead > 0);
		sourceFile.Close();

		// 通知用户,当前的状态信息
		nCompleted = nPreCount++;
		::PostMessage(m_hWndNotify, WM_CUTTERSTATUS, 0, nCompleted);
	}
	while(TRUE);

	// 通知用户,工作完成
	::PostMessage(m_hWndNotify, WM_CUTTERSTOP, exitSuccess, nCompleted);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -