📄 lz77.cpp
字号:
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 + -