欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【信源编码 作业三】基于LZO算法的词典压缩器实现

程序员文章站 2022-03-22 23:02:10
...

1. LZO算法的概述
LZO 是致力于解压速度的一种数据压缩算法,LZO 是 Lempel-Ziv-Oberhumer 的缩写。这个算法是无损算法,参考实现程序是线程安全的。 实现它的一个*软件工具是lzop。最初的库是用 ANSI C 编写、并且遵从 GNU通用公共许可证发布的,现在 LZO 有用于 Perl、Python 以及 Java 的各种版本。
LZO 库实现了许多有下述特点的算法:
* 解压简单,速度非常快。
* 解压不需要内存。
* 压缩相当地快。
* 压缩需要 64 kB 的内存。
* 允许在压缩部分以损失压缩速度为代价提高压缩率,解压速度不会降低。
* 包括生成预先压缩数据的压缩级别,这样可以得到相当有竞争力的压缩比。
* 另外还有一个只需要 8 kB 内存的压缩级别。
* 算法是线程安全的。
* 算法是无损的。
2. LZO算法的编解码器
先下载好lzo-2.10,目录如下所示:

lzo-2.10
|–asm
|–autoconf
|–B
|–doc
|–examples
|–include
|–lzotest
|–minilzo
|–src
|–tests
|–util
词典压缩器的实现步骤如下所示:

(1)选择代压缩文件按钮:

void CcompressDlg::OnBnClickedButton3()  
{  
    // TODO: 在此添加控件通知处理程序代码  
    CString strFile = _T("");  

    CFileDialog    dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.cfg)|*.cfg|All Files (*.*)|*.*||"), NULL);  

    if (dlgFile.DoModal())  
    {  
        strFile = dlgFile.GetPathName();  
    }  

    UpdateData(true);          // 获取数据  
    path = strFile;  
    UpdateData(false);         // 更新数据  
}  

(2)选择解压缩文件按钮:

void CcompressDlg::OnBnClickedButton4()  
{  
    // TODO: 在此添加控件通知处理程序代码  
    CString strFile = _T("");  

    CFileDialog    dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.cfg)|*.cfg|All Files (*.*)|*.*||"), NULL);  

    if (dlgFile.DoModal())  
    {  
        strFile = dlgFile.GetPathName();  
    }  

    UpdateData(true);          // 获取数据  
    path_decompress = strFile;  
    UpdateData(false);         // 更新数据  
}  

(3)压缩按钮:

void CcompressDlg::OnBnClickedButton1()  
{  
    // TODO: 在此添加控件通知处理程序代码  
#ifdef _UNICODE  
    LONG len1;  
    len1 = WideCharToMultiByte(CP_ACP, 0, path, -1, NULL, 0, NULL, NULL);  
    char *textPath = (char *)malloc(sizeof(char)*(len1 + 1));  
    memset(textPath, 0, len1 + 1);  
    WideCharToMultiByte(CP_ACP, 0, path, -1, textPath, len1 + 1, NULL, NULL);  
#else  
    ptr = new char[str.GetAllocLength() + 1];  
#endif  
    err = fopen_s(&ifp, textPath, "rb");  
    if (err == 0)  
    {  
        printf("Thefile'crt_fopen_s.c'wasopened\n");  
    }  
    fseek(ifp, 0, SEEK_END);  
    unsigned long len = ftell(ifp);  
    myInLen = len;  
    fseek(ifp, 0, SEEK_SET);  
    cpTemp = (char*)malloc(len * sizeof(char));  
    fread(cpTemp, sizeof(char), len, ifp);  
    char *in = cpTemp;  
    char *out = (char*)malloc((len + len / 16 + 64 + 3) * sizeof(char));  

    if (lzo_init() != LZO_E_OK)  
    {  
        printf("internal error - lzo_init() failed !!!\n");  
        printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");  

    }  

    lzo_uint in_len;  
    in_len = len;  
    lzo_memset(in, 0, in_len);  
    lzo_uint out_len;  

    int r;  

    r = lzo1x_1_compress((unsigned char*)in, in_len, (unsigned char*)out, &out_len, wrkmem);  
    char mess[256];  

    if (r == LZO_E_OK)  
    {  
        sprintf_s(mess, sizeof(mess),  "压缩成功!\n\n原文件大小:%lu bytes\n压缩后大小:%lu bytes\n\n解压得到的文件“compress.txt”保存于工程目录下",  
            (unsigned long)in_len, (unsigned long)out_len);  
        MessageBox(CString(mess));  

    }  
    else  
    {  
        /* this should NEVER happen */  
        sprintf_s(mess, sizeof(mess), "压缩失败!\n %d\n", r);  
        MessageBox(CString(mess));  
    }  
    /* check for an incompressible block */  
    if (out_len >= in_len)  
    {  
        sprintf_s(mess, sizeof(mess), "未压缩!\n");  
        MessageBox(CString(mess));  
    }  

    err = fopen_s(&ofp, ".\\compress.txt", "wb");  
    fwrite(out, sizeof(char), out_len, ofp);  

    fclose(ifp);  
    fclose(ofp);  
    free(cpTemp);  
    free(out);  
    free(textPath);  

}  

(4)解压缩按钮:

void CcompressDlg::OnBnClickedButton2()  
{  
    // TODO: 在此添加控件通知处理程序代码  
#ifdef _UNICODE  
    LONG len1;  
    len1 = WideCharToMultiByte(CP_ACP, 0, path_decompress, -1, NULL, 0, NULL, NULL);  
    char *textPath = (char *)malloc(sizeof(char)*(len1 + 1));  
    memset(textPath, 0, len1 + 1);  
    WideCharToMultiByte(CP_ACP, 0, path_decompress, -1, textPath, len1 + 1, NULL, NULL);  
#else  
    ptr = new char[str.GetAllocLength() + 1];  
#endif  
    err = fopen_s(&ifp, textPath, "rb");  
    if (err == 0)  
    {  
        printf("Thefile'crt_fopen_s.c'was opened\n");  
    }  
    fseek(ifp, 0, SEEK_END);  
    unsigned long len = ftell(ifp);  
    fseek(ifp, 0, SEEK_SET);  
    cpTemp = (char*)malloc(len * sizeof(char));  
    fread(cpTemp, sizeof(char), len, ifp);  
    char *in = cpTemp;  
    char *out = (char *)malloc(len*100* sizeof(char));  
    memset(out, 0, len * 100 * sizeof(char));  

    int r;  
    lzo_uint new_len;  
    r = lzo1x_decompress((unsigned char*)in, len, (unsigned char*)out, &new_len, NULL);  

    char mess[256];  
    if (r == LZO_E_OK && new_len == myInLen)  
    {  
        sprintf_s(mess, sizeof(mess), "解压成功!\n\n待解压文件大小: %lu bytes\n解压后文件大小: %lu bytes\n\n解压得到的文件“decompress.txt”保存于工程目录下",  
            (unsigned long)len, (unsigned long)new_len);  
        MessageBox(CString(mess));  
    }  
    else  
    {  
        /* this should NEVER happen */  
        sprintf_s(mess, sizeof(mess), "解压失败! %d\n", r);  
        MessageBox(CString(mess));  
    }  
    err = fopen_s(&ofp, ".\\decompress.txt", "wt+");  
    fwrite(out, sizeof(char), new_len, ofp);  

    fclose(ifp);  
    fclose(ofp);  
    free(cpTemp);  
    free(textPath);  
    free(out);  
} 

界面效果如下所示:
【信源编码 作业三】基于LZO算法的词典压缩器实现
压缩结果如下所示:
【信源编码 作业三】基于LZO算法的词典压缩器实现
解压缩结果如下所示:
【信源编码 作业三】基于LZO算法的词典压缩器实现