DLib压缩解压程序示例

/*

    这是一个示例程序,使用了Dlib库的compress_stream和cmd_line_parser组件。

    这个示例实现了一个简单实用的命令行压缩程序。


    当使用-h选项时候,程序输出如下:

        使用: compress_stream_ex (-c|-d|-l) --in input_file --out output_file
        选项:
          -c            表示要执行压缩文件操作.
          -d            表示要执行解压文件操作.
          --in <arg>    此选项带一个参数,指定要压缩或解压的文件名称.
          --out <arg>   此选项带一个参数,指定输出文件名称.

        其他选项:
          -h            显示帮助信息.
          -l <arg>      设置压缩级别[1-3], 3是最大压缩,默认值是2.

*/




#include <dlib/compress_stream.h>
#include <dlib/cmd_line_parser.h>
#include <iostream>
#include <fstream>
#include <string>

// 为要使用的compress_stream版本做一个typedef定义
typedef dlib::compress_stream::kernel_1da cs1;
typedef dlib::compress_stream::kernel_1ea cs2;
typedef dlib::compress_stream::kernel_1ec cs3;


using namespace std;
using namespace dlib;


int main(int argc, char** argv)
{
    try
    {
        command_line_parser parser;

        // 首先,定义需要的命令行参数
        // 添加 -c 选项,并给出描述信息
        parser.add_option("c","表示要执行压缩文件操作.");
        parser.add_option("d","表示要执行解压文件操作.");
        // 添加需带一个参数的选项 --in
        parser.add_option("in","此选项带一个参数,指定要压缩或解压的文件名称.",1);
        // 添加需带一个参数的选项 --in
        parser.add_option("out","此选项带一个参数,指定输出文件名称.",1);

        // 在下面代码中,使用parser.print_options()方法在屏幕上打印所有选项.
        // 在添加这些选项之前,我们可以调用 set_group_name()将一些选项分组在一起。
        // 通常,可以通过调用set_group_name()来创建多个分组。这里我们仅创建一个。
        parser.set_group_name("其他选项");
        parser.add_option("h","显示帮助信息.");
        parser.add_option("l","设置压缩级别[1-3], 3是最大压缩,默认值是2.",1);


        // 现在,将解析命令行参数
        parser.parse(argc,argv);


        // 现在,将使用parser(解析器)去验证命令行参数.
        // 如果一下任意检验失败,将抛出异常。该异常包含一条消息,告诉错误原因.

        // 首先,需要检查一下,没有提供任何选项的命令行。
        // 这需要定义一个数组,其中包含不应该多次出现的选项,然后调用check_one_time_options()
        const char* one_time_opts[] = {"c", "d", "in", "out", "h", "l"};
        parser.check_one_time_options(one_time_opts);
        // 下面,检查用户是否同时提供 -c 和 -d 选项
        parser.check_incompatible_options("c", "d");

        // 下面检查 -l 选项,其参数应是1到3范围内的整数
        // 也就是说,它可以通过dlib::string_assign转换到1、2或3。请注意,如果是要范围是1.0到3.0的
        // 浮点数,则可以给出范围1.0到3.0。或者向check_option_arg_range()函数的template参数显示
        // 提供一个float或double类型.
        parser.check_option_arg_range("l", 1, 3);

        // 'l'选项是'c'选项的子选项。也就是说只能在压缩的时候选择压缩级别。
        // 下面命令检查列出的子选项给出的时候,父选项是否存在。
        const char* c_sub_opts[] = {"l"};
        parser.check_sub_options("c", c_sub_opts);

        // 检查命令行中是否给出了-h选项
        if (parser.option("h"))
        {
            // 显示所有命令行选项
            cout << "使用: compress_stream_ex (-c|-d|-l) --in input_file --out output_file\n";
            // 此函数打印出一个格式很好的列表,来展示parser具有所有选项
            parser.print_options();
            return 0;
        }

        // 获取压缩级别选项值,如果没有则使用默认的2
        int compression_level = get_option(parser,"l",2);


        // 确保提供了c或d两个选项之一
        if (!parser.option("c") && !parser.option("d"))
        {
            cout << "命令行错误:\n   你必须指定 -c 或 -d 选项.\n";
            cout << "\n使用 -h 选项查看更多信息." << endl;
            return 0;
        }


        string in_file;
        string out_file;

        // 检查用户是否给出了输入文件名
        // 如果是,在获取给定的文件名
        if (parser.option("in"))
        {
            in_file = parser.option("in").argument();
        }
        else
        {
            cout << "命令行错误:\n   你必须指定一个输入文件.\n";
            cout << "\n使用 -h 选项查看更多信息." << endl;
            return 0;
        }


        // 检查用户是否给出了输入文件名
        // 如果是,在获取给定的文件名
        if (parser.option("out"))
        {
            out_file = parser.option("out").argument();
        }
        else
        {
            cout << "命令行错误:\n   你必须指定一个输出文件.\n";
            cout << "\n使用 -h 选项查看更多信息." << endl;
            return 0;
        }


        // 打开我们将要读取和写入的文件
        ifstream fin(in_file.c_str(),ios::binary);
        ofstream fout(out_file.c_str(),ios::binary);

        // 确保文件打开正确
        if (!fin)
        {
            cout << "打开文件 " << in_file << " 出错.\n";
            return 0;
        }

        if (!fout)
        {
            cout << "创建文件 " << out_file << " 出错.\n";
            return 0;
        }



        // 现在执行实际的压缩或解压缩
        if (parser.option("c"))
        {
            // 将压缩级别保存到输出文件
            serialize(compression_level, fout);

            switch (compression_level)
            {
                case 1:
                    {
                        cs1 compressor;
                        compressor.compress(fin,fout);
                    }break;
                case 2:
                    {
                        cs2 compressor;
                        compressor.compress(fin,fout);
                    }break;
                case 3:
                    {
                        cs3 compressor;
                        compressor.compress(fin,fout);
                    }break;
            }
        }
        else
        {
            // 从输入文件获取压缩级别
            deserialize(compression_level, fin);

            switch (compression_level)
            {
                case 1:
                    {
                        cs1 compressor;
                        compressor.decompress(fin,fout);
                    }break;
                case 2:
                    {
                        cs2 compressor;
                        compressor.decompress(fin,fout);
                    }break;
                case 3:
                    {
                        cs3 compressor;
                        compressor.decompress(fin,fout);
                    }break;
                default:
                    {
                        cout << "压缩文件有错误,无效的压缩级别。" << endl;
                    }break;
            }
        }




    }
    catch (exception& e)
    {
        // 请注意,这将捕获所有cmd_line_parse_error异常并打印默认消息。
        cout << e.what() << endl;
    }
}
posted @ 2017-03-27 14:41  乌合之众  阅读(932)  评论(0编辑  收藏  举报
clear