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

📄 lz77.cpp

📁 在Lz77的基础上修改
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	return true;
}



/////////////////////////////////////////////
// 压缩一段字节流
// src - 源数据区
// srclen - 源数据区字节长度
// dest - 压缩数据区,调用前分配srclen+5字节内存
// 返回值 > 0 压缩数据长度
// 返回值 = 0 数据无法压缩
// 返回值 < 0 压缩中异常错误
int CCompressLZ77::Compress(BYTE* src, int srclen, BYTE* dest)
{
	int i;
	CurByte = 0; CurBit = 0;	
	int off, len;

	if (srclen > 65536) 
		return -1;

	pWnd = src;
	_InitSortTable();
	for (i = 0; i < srclen; i++)
	{		
		if (CurByte >= srclen)
			return 0;
		if (_SeekPhase(src, srclen, i, &off, &len))
		{			
			// 输出匹配术语 flag(1bit) + len(γ编码) + offset(最大16bit)
			_OutCode(dest, 1, 1, FALSE);
			_OutCode(dest, len, 0, TRUE);

			// 在窗口不满64k大小时,不需要16位存储偏移
			_OutCode(dest, off, UpperLog2(nWndSize), FALSE);
						
			_ScrollWindow(len);
			i += len - 1;
		}
		else
		{
			// 输出单个非匹配字符 0(1bit) + char(8bit)
			_OutCode(dest, 0, 1, FALSE);
			_OutCode(dest, (DWORD)(src[i]), 8, FALSE);
			_ScrollWindow(1);
		}
	}
	int destlen = CurByte + ((CurBit) ? 1 : 0);
	if (destlen >= srclen)
		return 0;
	return destlen;
}

bool CCompressLZ77::DecompressFile(char* zipFile, char* unZipFile)
{
    WORD flag1, flag2;
	BYTE soubuf[65536];
	BYTE destbuf[65536 + 16];
	FILE* in = fopen(zipFile, "rb");
	FILE* out = out = fopen(unZipFile, "wb");
	if (out == NULL)
	{
		fclose(in);
		return false;
	}
	fseek(in, 0, SEEK_END);
	long soulen = ftell(in);
	fseek(in, 0, SEEK_SET);
	int last = soulen, act;
	while (last > 0)
	{
		fread(&flag1, sizeof(WORD), 1, in);
		fread(&flag2, sizeof(WORD), 1, in);
		last -= 2 * sizeof(WORD);
		if (flag1 == 0)
			act = 65536;
		else
			act = flag1;
		last-= flag2 ? (flag2) : act;

		if (flag2 == flag1)
		{
			fread(soubuf, act, 1, in);				
		}
		else
		{
			fread(destbuf, flag2, 1, in);
			if (!Decompress((BYTE*)soubuf, act, (BYTE*)destbuf))
			{
				fclose(in);
				fclose(out);
				return -1;
			}
		}
		fwrite((BYTE*)soubuf, act, 1, out);				
	}
	fclose(in);
	fclose(out);
	return TRUE;
}
/////////////////////////////////////////////
// 解压缩一段字节流
// src - 接收原始数据的内存区
// srclen - 源数据区字节长度
// dest - 压缩数据区
// 返回值 - 成功与否
BOOL CCompressLZ77::Decompress(BYTE* src, int srclen, BYTE* dest)
{
	int i;
	CurByte = 0; CurBit = 0;
	pWnd = src;		// 初始化窗口
	nWndSize = 0;

	if (srclen > 65536) 
		return FALSE;
	
	for (i = 0; i < srclen; i++)
	{		
		BYTE b = GetBit(dest[CurByte], CurBit);
		MovePos(&CurByte, &CurBit, 1);
		if (b == 0) // 单个字符
		{
			CopyBits(src + i, 0, dest + CurByte, CurBit, 8);
			MovePos(&CurByte, &CurBit, 8);
			nWndSize++;
		}
		else		// 窗口内的术语
		{
			int q = -1;
			while (b != 0)
			{
				q++;
				b = GetBit(dest[CurByte], CurBit);
				MovePos(&CurByte, &CurBit, 1);				
			}
			int len, off;
			DWORD dw = 0;
			BYTE* pb;
			if (q > 0)
			{				
				pb = (BYTE*)&dw;
				CopyBits(pb + (32 - q) / 8, (32 - q) % 8, dest + CurByte, CurBit, q);
				MovePos(&CurByte, &CurBit, q);
				InvertDWord(&dw);
				len = 1;
				len <<= q;
				len += dw;
				len += 1;
			}
			else
				len = 2;

			// 在窗口不满64k大小时,不需要16位存储偏移
			dw = 0;
			pb = (BYTE*)&dw;
			int bits = UpperLog2(nWndSize);
			CopyBits(pb + (32 - bits) / 8, (32 - bits) % 8, dest + CurByte, CurBit, bits);
			MovePos(&CurByte, &CurBit, bits);
			InvertDWord(&dw);
			off = (int)dw;
			// 输出术语
			for (int j = 0; j < len; j++)
			{
				_ASSERT(i + j <  srclen);
				_ASSERT(off + j <  _MAX_WINDOW_SIZE);
				
				src[i + j] = pWnd[off + j];
			}
			nWndSize += len;
			i += len - 1;
		}
		// 滑动窗口
		if (nWndSize > _MAX_WINDOW_SIZE)
		{
			pWnd += nWndSize - _MAX_WINDOW_SIZE;
			nWndSize = _MAX_WINDOW_SIZE;			
		}
	}

	return TRUE;
}

BOOL CCompressLZ77::CompressDir(char* srcDir, char* zipFile, bool includeSub)
{
    WIN32_FIND_DATA FindFileData;
	HANDLE	hFind;
	BOOL	bFinished = FALSE;
	BOOL	ret = FALSE;
	char	tempFileFind[200];
	DWORD	nBytesToRead,nBytesRead, nBytesWrited;
	sprintf(tempFileFind,"%s\\*.*", srcDir); 
	hFind = FindFirstFile(tempFileFind, &FindFileData);
	if (hFind == INVALID_HANDLE_VALUE) 
	{
		printf ("Invalid File Handle. GetLastError reports %d\n", GetLastError ());
		return FALSE;
	} 	
	while (!bFinished)
	{		
		//如果不是.和..
		if(strcmp(FindFileData.cFileName, ".")!=0 && strcmp(FindFileData.cFileName,"..")!=0)
		{
			//如果是目录
			if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				if (includeSub)
				{
					char tempDir[MAX_PATH];
					char tempArch[MAX_PATH];
					sprintf(tempDir,"%s\\%s", srcDir, FindFileData.cFileName);
					sprintf(tempArch,"%s\\%s.archd", srcDir, FindFileData.cFileName);
					if(!CompressDir(tempDir,tempArch))
						return FALSE;
					BYTE	buffer[MAX_BUF];
					char	tempFile[MAX_PATH];
					DWORD	iFileSize;
					DWORD	iFileNameSize;
					sprintf(tempFile,"%s\\%s", srcDir, FindFileData.cFileName); 			
					//将文件写入打包文件arch中,首先为文件长度   4+文件名长度+文件长度+字节
					HANDLE destHanle = ::CreateFile(zipFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
					//ftDst.OpenFile(zipFile);
					HANDLE srcHanle = ::CreateFile(tempArch, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
					::SetFilePointer(destHanle, 0, NULL, FILE_END);
					sprintf(tempFile,"%s.archd", FindFileData.cFileName);
					iFileSize = GetFileSize(srcHanle, NULL);
					iFileNameSize = strlen(tempFile);
					//    4B			4B				文件名		文件内容
					//    文件名长度	文件内容长度    相对路径
					WriteFile(destHanle, (char *)&iFileNameSize, 4, &nBytesWrited, NULL);
					WriteFile(destHanle, (char *)&iFileSize, 4, &nBytesWrited, NULL);
					WriteFile(destHanle, tempFile, iFileNameSize, &nBytesWrited, NULL);
					do
					{
						ret = ReadFile(srcHanle, buffer, 512, &nBytesRead, NULL) ; 
						// Check for end of file. 
						if (ret &&  (nBytesRead == 0) ) 
						{ 
							break;
						}	
						ret = ::WriteFile(destHanle,buffer,nBytesRead,&nBytesToRead,NULL);		
						if(!ret)
						{
							return FALSE;
						}
					}while(TRUE);	
					CloseHandle(srcHanle);
					CloseHandle(destHanle);
					//删除生成的临时文件*.archd
					DeleteFile(tempArch);
				}
			}
			//如果是文件则首先压缩文件,然后在写入到目标文件中
			else 
			{					
				if(strstr(FindFileData.cFileName, ".archd"))
				{
					
				}
				else
				{
					BYTE	buffer[MAX_BUF];
					char	tempFileCompressName[MAX_PATH];
					char	tempFile[MAX_PATH];
					DWORD	iFileSize;
					DWORD	iFileNameSize;						
					sprintf(tempFile,"%s\\%s", srcDir, FindFileData.cFileName); 
					GetCompressFileName(tempFileCompressName, tempFile);
					//压缩文件 tempFileCompressName
					CompressFile(tempFile, tempFileCompressName);				
					//将文件写入打包文件arch中,首先为文件长度   4+文件名长度+文件长度+字节
					HANDLE destHanle = ::CreateFile(zipFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
					//ftDst.OpenFile(zipFile);
					HANDLE srcHanle = ::CreateFile(tempFileCompressName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
					
					::SetFilePointer(destHanle, 0, NULL, FILE_END);
					iFileSize = GetFileSize(srcHanle, NULL);
					iFileNameSize = strlen(FindFileData.cFileName);
					//    4B			4B				文件名		文件内容
					//    文件名长度	文件内容长度    相对路径
				    WriteFile(destHanle, (char *)&iFileNameSize, 4, &nBytesWrited, NULL);
					WriteFile(destHanle, (char *)&iFileSize, 4, &nBytesWrited, NULL);
					WriteFile(destHanle, FindFileData.cFileName, iFileNameSize, &nBytesWrited, NULL);
					do
					{
						ret = ReadFile(srcHanle, buffer, 512, &nBytesRead, NULL) ; 
						// Check for end of file. 
						if (ret &&  (nBytesRead == 0) ) 
						{ 
							break;
						}	
						ret = ::WriteFile(destHanle,buffer,nBytesRead,&nBytesToRead,NULL);		
						if(!ret)
						{
							return FALSE;
						}
					}while(TRUE);	
					CloseHandle(srcHanle);
					CloseHandle(destHanle);
					//删除生成的临时文件*.liz
					DeleteFile(tempFileCompressName);	

				}				
			}
		}
		//查找下一个文件
		if (!FindNextFile (hFind, &FindFileData))
		{
			bFinished = TRUE;
			if (GetLastError () == ERROR_NO_MORE_FILES)
			{
				//printf(TEXT("Found all of the files."));
			}
			else
			{
				printf(TEXT("Unable to find next file."));
			}
		}
	}
	// Close the search handle.
	
	if (!FindClose (hFind))
	{
		printf(TEXT("Unable to close search handle."));
	}
	return TRUE;
}

BOOL CCompressLZ77::DeCompressDir(char* zipFile, char* destDir)
{
    char szUnArchDir[MAX_PATH];	
	DWORD	nBytesRead, nBytesWrited;
	BOOL ret;
	if(destDir == NULL)
	{
		strcpy(szUnArchDir, zipFile);
		char *p = szUnArchDir;
		p = strstr(szUnArchDir, ".");
		*p = 0;
	}
	CreateDirectory(destDir, NULL);	
	HANDLE srcHandle = ::CreateFile(zipFile, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	unsigned long iFileDataSize;
	unsigned long iFileNameSize;
	
	do 
	{
		ret = ReadFile(srcHandle, &iFileNameSize, 4, &nBytesRead, NULL); 
		// Check for end of file. 
		if (ret &&  (nBytesRead == 0) ) 
		{ 
			break;
		}	
		ret = ReadFile(srcHandle, &iFileDataSize, 4, &nBytesRead, NULL); 
		// Check for end of file. 
		if (ret &&  (nBytesRead == 0) ) 
		{ 
			break;
		}	
		char *FileName = new char[iFileNameSize+1];
		char *FileData = new char[iFileDataSize+1];
		//文件名
		ret = ReadFile(srcHandle, FileName, iFileNameSize, &nBytesRead, NULL); 
		// Check for end of file. 
		if (ret &&  (nBytesRead == 0) ) 
		{ 
			break;
		}
		FileName[iFileNameSize] = 0;
		//文件数据
		ret = ReadFile(srcHandle, FileData, iFileDataSize, &nBytesRead, NULL); 
		// Check for end of file. 
		if (ret &&  (nBytesRead == 0) ) 
		{ 
			break;
		}
		FileData[iFileDataSize] = 0;
		if(strstr(FileName, ".archd"))
		{
			char TempFileName[MAX_PATH];
			char TempDirName[MAX_PATH];
			char *p;
			sprintf(TempFileName, "%s\\%s", destDir, FileName);
			sprintf(TempDirName, "%s\\%s", destDir, FileName);

			//去掉文件的后缀名
			p = strstr(TempDirName, ".");
			*p =0;
			HANDLE destHandle = ::CreateFile(TempFileName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
			WriteFile(destHandle, FileData, iFileDataSize, &nBytesWrited,NULL);			
			CloseHandle(destHandle);
			//CreateDirectory(TempDirName, NULL);
//			if(!CreateDirectory(TempDirName, NULL))
//			{	
//				printf("创建文件夹%s失败\n", dir);
//			}
			DeCompressDir(TempFileName, TempDirName);
			DeleteFile(TempFileName);
		}
		else
		{
			char TempFileName[MAX_PATH];
			char TempFileComName[MAX_PATH];
			sprintf(TempFileName, "%s\\%s", destDir, FileName);
			GetCompressFileName(TempFileComName, TempFileName);
			
			HANDLE destHandle = ::CreateFile(TempFileComName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
			WriteFile(destHandle, FileData, iFileDataSize, &nBytesWrited,NULL);			
			CloseHandle(destHandle);
			DecompressFile(TempFileComName, TempFileName);			
			DeleteFile(TempFileComName);
		}
		delete [] FileName;
		delete [] FileData;
	} while(TRUE);
	CloseHandle(srcHandle);
	return TRUE;
}

⌨️ 快捷键说明

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