C語言課程設計---RLE壓縮算法
RLE算法的介紹
RLE全稱(run-length encoding),翻譯為游程編碼,又譯行程長度編碼,又稱變動長度編碼法(run coding),在控制論中對於二值圖像而言是一種編碼方法,對連續的黑、白像素數(游程)以不同的碼字進行編碼。游程編碼是一種簡單的非破壞性資料壓縮法,其好處是加壓縮和解壓縮都非常快。其方法是計算連續出現的資料長度壓縮之。
如圖為RLE算法描述
RLE在用於二進制多重復的情況下比較好, 特點是可以做到無損壓縮, 但是用於字符多且重復性差的情況下可能做到事倍功半, 比如 ABCDEFG經壓縮后將成為1A1B1C1D1E1F1G, 字符串整整擴大了一倍.
c語言實現
為了模擬出有重復性的數據, 我以如下方式進行數據生成:
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("file.txt","w",stdout); //輸出重定向,輸出到文件
srand(time(0)); //以當前時間作為種子
char x;
for(int i = 0; i <= 10000000; ++i){
x = 'a' + rand()%26;
cout<<x<<x<<x<<x;
}
return 0;
}
RLE算法代碼:
編寫一個程序,可以在命令行輸入參數,完成指定文件的壓縮解壓
命令行參數如下
rle file1 –c(-d) file2
第一個參數為可執行程序名稱,第二個參數為原始文件名,第三個參數為壓縮或解壓縮選項,第四個參數為新文件名
#include<bits/stdc++.h>
using namespace std;
void zip(char* filename,char *outfile){
FILE *in, *out;
int filelen;
char cur, tmp;
if(!(in = fopen(filename,"rb")))
cout<<"文件打開失敗"<<endl;
else
{
out = fopen(outfile,"wb");
cur = fgetc(in);
tmp = cur;
filelen = 1;
while(!feof(in)){
cur = fgetc(in);
if(cur == tmp){
filelen++;
}
else{
fputc(filelen+'0',out);
fputc(tmp,out);
tmp = cur;
filelen = 1;
}
}
}
fclose(in);
fclose(out);
}
void unzip(char *filename,char *outfile){
FILE *in, *out;
int filelen;
char cur; //光標
if(!(in = fopen(filename,"rb")))
cout<<"文件打開失敗"<<endl;
else
{
out = fopen(outfile,"wb");
while(!feof(in)){
filelen = fgetc(in)-'0';
if(feof(in))break; //feof的問題,折騰了好一會,不好表述,總之在feof應當在每一次讀操作之后判斷是否到文件末, 不然會造成多讀一次的錯誤
cur = fgetc(in);
while(filelen--)
fputc(cur,out);
}
}
fclose(in);
fclose(out);
}
int main(int argc,char *argv[]){
if(!strcmp(argv[2], "-d")){
unzip(argv[1], argv[3]);
cout<<"decompress finished"<<endl;
}
else if(!strcmp(argv[2],"-c")){
zip(argv[1], argv[3]);
cout<<"compress finished"<<endl;
}
else
cout<<"輸入參數有誤,請重新檢查,-c : compress; -d : decompress"<<endl;
return 0;
}
其中應用到了兩個之前沒用過的函數fgetc和fputc, 這里簡單記錄一下:
fgetc是一種計算機C語言中的函數。意為從文件指針stream指向的文件中讀取一個字符,讀取一個字節后,光標位置后移一個字節。
函數格式:int fgetc(FILE *stream)
fputc函數功能: 將字符ch寫到文件指針fp所指向的文件的當前寫指針的位置。
函數格式:int fputc (int c, FILE *fp)
結果:
源文件----35MB
壓縮后文件----15MB