043.哈夫曼编码应用于压缩文件


博主的 Github 地址


  • 注意:
    本篇哈夫曼编码的实现代码依赖于上一篇的内容,
    本文是在上篇的基础上增加哈夫曼编码实现解压缩的内容.

1. 哈夫曼编码实现文件压缩

  • 要求
    给定一个图片文件, 对其进行无损压缩

  • 思路
    读取文件 -> 得到哈夫曼编码表 -> 完成压缩

1.1. 代码实现

  • 以下类方法均放入上一篇中的 HuffmanCode.java 中即可使用
1.1.1. 压缩方法
//region 编写方法, 将一个文件进行压缩

    /**
     * @param srcFilePath 传入目标文件的路径
     * @param dstFilePath 压缩后存放文件的路径
     */
    public static void zipFile(String srcFilePath, String dstFilePath) {
        //定义一个文件输入流
        FileInputStream is = null;
        //定义一个文件输出流
        OutputStream os = null;
        ObjectOutputStream oos = null;
        try {
            //region 0. 先创建文件的输入流和输出流
            //创建文件输入流
            is = new FileInputStream(srcFilePath);
            //创建文件输出流
            os = new FileOutputStream(dstFilePath);
            //endregion

            //region 1. 对源文件进行压缩
            //创建一个和源文件大小一致的字节数组
            byte[] file_arr = new byte[is.available()];
            //读取文件
            is.read(file_arr);
            //将字节数组转换成结点列表
            List<TreeNode> node_list = getNodes(file_arr);
            //根据结点列表生成哈夫曼树
            TreeNode huffman_tree_root = createHuffmanTreeByList(node_list);
            //获取哈夫曼编码并存储在Map当中
            Map<Byte, String> the_huffman_code = getHuffmanCode(huffman_tree_root);
            //根据哈夫曼编码表来取得新的压缩后的byte字节数组
            byte[] zip_file_arr = transByteArray(file_arr, the_huffman_code);
            //endregion

            //region 输出并存放压缩文件
            //创建一个和文件输出流关联的ObjectOutputStream
            oos = new ObjectOutputStream(os);
            //把哈夫曼编码后的字节数组写入压缩文件
            oos.writeObject(zip_file_arr);
            //以对象流的方式写入哈夫曼编码, 为了以后恢复源文件时使用, 一定要写入, 否则文件恢复不了
            oos.writeObject(the_huffman_code);
            //endregion

        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                //关闭文件输入流
                is.close();
                //关闭文件输出流
                os.close();
                oos.close();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    //endregion

2. 哈夫曼编码实现文件解压

  • 要求
    将上面利用哈夫曼编码进行压缩的文件恢复为原来的文件

  • 思路
    读取压缩文件(包括数据和哈夫曼编码表) -> 完成解压, 文件恢复

2.1. 代码实现

2.1.1. 解压方法
    //region 编写方法完成对压缩文件的解压

    /**
     * @param zipFilePath 压缩文件的路径
     * @param unzipToPath 解压后存放恢复文件的路径
     */
    public static void unzipFile(String zipFilePath, String unzipToPath) {
        //定义文件的输入流
        InputStream is = null;
        //定义对象输入流
        ObjectInputStream ois = null;
        //定义文件的输出流
        OutputStream os = null;

        try {
            //region 0. 先创建输入输出流, 并读取压缩后的字节数组和哈夫曼编码表
            //创建文件输入流
            is = new FileInputStream(zipFilePath);
            //创建一个和is关联的对象输入流
            ois = new ObjectInputStream(is);
            //读取字节数组 zip_file_arr
            byte[] zip_file_arr = (byte[]) ois.readObject();
            //读取哈夫曼编码表 the_huffman_code
            Map<Byte, String> the_huffman_code = (Map<Byte, String>) ois.readObject();
            //endregion

            //region 1. 对压缩后的字节数组进行解码同时恢复和输出文件
            //对文件进行解码
            byte[] origin_file_arr = decodeByteArray(the_huffman_code, zip_file_arr);
            //将解码后的源文件数组输出
            os = new FileOutputStream(unzipToPath);
            os.write(origin_file_arr);
            //endregion
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                //关闭文件输入输出流
                os.close();
                ois.close();
                is.close();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    //endregion

3. 哈夫曼编码对文件的压缩和解压测试

  • 测试流程用到的代码
    //测试哈夫曼编码压缩文件
    //输入源文件的路径, 这里的源文件是一个大小为473KB的图片
    String srcFilePath = "d://test.bmp";
    //定义一个输出压缩文件的路径
    String zipFilePath = "d://zip_test_bmp.leozip";
    //调用压缩文件的方法, 压缩后得到一个120KB的文件
    HuffmanCode.zipFile(srcFilePath, zipFilePath);

    //定义一个输出解压后的源文件的路径
    String unzipToPath = "d://unzip_test.bmp";
    //调用解压文件的方法, 解压后获取得源文件
    HuffmanCode.unzipFile(zipFilePath, unzipToPath);
  • 获取一个图片文件

    • 源文件大小是 472KB
      step1
  • 对文件进行压缩

    • 文件压缩后大小变为 119KB
      step2
  • 对文件进行解压

    • 解压后获取到源文件 大小一致 为472KB
      step3

4. 哈夫曼编码解压缩文件注意事项

  1. 若文件本身已是经压缩处理的, 再使用哈夫曼编码压缩效率不会有明显变化
    (比如视频, ppt 等文件)

  2. 哈夫曼编码是按字节来处理的, 因此可处理所有的文件
    (二进制文件, 文本文件等)

  3. 若一个文件中的内容重复的数据不多, 压缩的效果也不会很明显
    (图片简单像素重复多, 压缩率则随之增高)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值