📄 rlezip.cpp
字号:
#include <fstream>
#include <iostream>
#include <windows.h>
#include <direct.h>
#include <string>
#include <iomanip>
using namespace std;
ifstream fin;
ofstream fout;
int totalinsize = 0, outsize = 0;
void rle_rep1(unsigned char *out, unsigned int *outpos, unsigned char marker, unsigned char symbol)
{
unsigned int idx;
idx = *outpos;
if(symbol == marker)
{
out[idx++] = marker;
out[idx++] = 0;
}
else
out[idx++] = symbol;
*outpos = idx;
}
void rle_rep(unsigned char *out, unsigned int *outpos, unsigned char marker, unsigned char symbol, unsigned int count )
{
unsigned int i, idx;
idx = *outpos;
if(count <= 3)
{
if(symbol == marker)
{
out[idx++] = marker;
out[idx++] = count - 1;
}
else
for(i = 0; i < count; ++ i)
out[idx++] = symbol;
}
else
{
out[idx++] = marker;
count--;
if(count >= 128)
out[idx++] = (count >> 8) | 0x80;
out[idx++] = count & 0xff;
out[idx++] = symbol;
}
*outpos = idx;
}
void rlezip_file(char *name)
{
int insize, t1 = 0, t2 = 0;
unsigned char *in, *out;
unsigned char byte1, byte2, marker;
unsigned int inpos, outpos = 0, count, i, histogram[256];
fin.seekg (0, ios::end);
insize = fin.tellg();
fin.seekg (0, ios::beg);
totalinsize += insize;
outsize = insize * 257 / 256 + 60;
in = new unsigned char[insize];
out = new unsigned char[outsize];
if (!in || !out)
{
cout <<"内存不足!" <<endl;
return ;
}
fin.read((char*)in, insize);
fout <<"[ff+" <<name <<"]";
if (insize < 1)
{
fout.put(0);
fout <<"[/ff]";
fout.close();
return ;
}
for(i = 0; i < 256; i++)
histogram[i] = 0;
for(i = 0; i < insize; i++)
histogram[in[i]]++ ;
marker = 0;
for(i = 1; i < 256; ++ i)
if(histogram[i] < histogram[marker])
marker = i;
out[0] = marker; outpos = 1; byte1 = in[0];
inpos = 1; count = 1;
if(insize >= 2)
{
byte2 = in[inpos++];
count = 2;
do
{
if(byte1 == byte2)
{
while((inpos < insize) && (byte1 == byte2) && (count < 32768))
{
byte2 = in[inpos++];
count++;
}
if(byte1 == byte2)
{
rle_rep(out, &outpos, marker, byte1, count);
if(inpos < insize)
{
byte1 = in[inpos++];
count = 1;
}
else
count = 0;
}
else
{
rle_rep(out, &outpos, marker, byte1, count-1);
byte1 = byte2;
count = 1;
}
}
else
{
rle_rep1(out, &outpos, marker, byte1);
byte1 = byte2;
count = 1;
}
if(inpos < insize)
{
byte2 = in[inpos++];
count = 2;
}
}
while((inpos < insize) || (count >= 2));
}
if(count == 1)
rle_rep1( out, &outpos, marker, byte1 );
fout.write((char *)out, outpos);
fout <<"[/ff]";
delete[] in;
delete[] out;
}
void rlezip_dir(char *source)
{
HANDLE f1;
WIN32_FIND_DATA fData;
char temp[50];
fout<<"[rr+" <<source <<"]";
strcpy(temp, "./"); strcat(temp, source);
_chdir(temp);
f1 = FindFirstFile(".//*", &fData);
do
{
if((fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
{
if (strcmp(fData.cFileName, ".") && strcmp(fData.cFileName, ".."))
{
rlezip_dir(fData.cFileName);
_chdir("../");
}
}
else
{
fin.open(fData.cFileName, ios::in|ios::binary);
rlezip_file(fData.cFileName);
fin.close();
}
}while(FindNextFile(f1,&fData));
fout <<"[/rr]";
}
int main(int arg, char *argv[])
{
char *destiny = argv[arg - 1], *p;
char temp[100] = "", cur[100];
int i, len;
double persent;
HANDLE f1;
WIN32_FIND_DATA fData;
fout.open(destiny, ios::out|ios::binary);
if (!fout)
{
cout <<"文件错误!" <<endl;
return 0;
}
if (strcmp(argv[1],"*") == 0) //相对路径所有文件
{
f1 = FindFirstFile(".//*",&fData);
do
{
if((fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
continue;
fin.open(fData.cFileName, ios::in|ios::binary);
if (!fin)
{
cout<<"无法读取文件!" <<endl;
continue;
}
rlezip_file(fData.cFileName);
fin.close();
} while(FindNextFile(f1,&fData));
}
else if (strstr(argv[1], ":\\") != NULL) //绝对路径压缩
{
len = strcspn(argv[1], "\\");
getcwd(cur, 100);
p = strrchr(argv[1], '\\');
len = strlen(argv[1]) - strlen(p) +1;
strncpy(temp, argv[1], len);
_chdir(temp);
rlezip_dir(p);
_chdir(cur);
}
else if (strchr(argv[1], '.') == NULL) //相对路径文件夹压缩
{
rlezip_dir(argv[1]);
_chdir("../");
}
else //文件压缩
{
for (i = 1; i < arg -1; i++)
{
fin.open(argv[i], ios::in|ios::binary);
if (!fin)
{
cout <<"无法读取文件!" <<endl;
continue;
}
rlezip_file(argv[i]);
fin.close();
}
}
fout.close();
fin.open(destiny, ios::in|ios::binary);
fin.seekg (0, ios::end);
outsize = fin.tellg();
persent = (double)outsize / (double)totalinsize * 100;
cout <<"压缩率: "<< setiosflags(ios::fixed) <<setprecision(1) <<persent<< "%" <<endl;
fin.close();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -