美文网首页
树结构入门教程-赫夫曼编码文件压缩

树结构入门教程-赫夫曼编码文件压缩

作者: 会上树的程序猿 | 来源:发表于2020-03-26 14:26 被阅读0次

    前面我们学习了赫夫曼的编码和解码的过程,我们操作的对象是一串字符串,而实质上赫夫曼的压缩和解压的过程不仅仅只针对于字符串的处理,而且文件也是可以的,如图片的压缩和解压,关于文件的压缩和解压我们本节来讲,我们来看看实际的案例.

    文件压缩要求

    假设给我们一张图片文件,要求我们进行无所压缩处理,由于我们之前做了很多前提工作,这里我们直接写代码实现即可

    代码实现过程:

    当然我们会利用前面一些公共的方法,这里就不在重复了,直接看代码:

     /**
     *
     * @param srcFilePath 带压缩文件的全路径
     * @param desFilePath 压缩过后的文件路径
     */
    public static void zipFile(String srcFilePath,String desFilePath){
        //1.创建文件的输入流来读取我们的文件
        FileInputStream inputStream = null;
        //2.创建输出流
        FileOutputStream outputStream = null;
        //3.创建ObjectOutputStream来关联我们的FileOutputStream
        ObjectOutputStream objectOutputStream = null;
        //创建一个和源文件大小一样的byte数组来存储我们读取的数据
        byte[] b = null;
        try {
            inputStream = new FileInputStream(srcFilePath);
             b = new byte[inputStream.available()];
             //读取file的内容到b数组中
             inputStream.read(b);
             //对源文件压缩
            byte[] huffmanByte = huffmanZip(b);
            //存放我们的压缩文件
            outputStream = new FileOutputStream(desFilePath);
            //关联文件文件输出流
            objectOutputStream = new ObjectOutputStream(outputStream);
            //将赫夫曼编码过后的字节数组写入(以object的形式)压缩文件
            objectOutputStream.writeObject(huffmanByte);
            //同样也把赫夫曼编码写入压缩文件
            objectOutputStream.writeObject(huffmanCodes);
    
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                inputStream.close();
                objectOutputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    因为是文件的处理这里涉及到了io流的操作.巧妙的是我们这里利用的是对象流(ObjectOutputStream)来处理,为什么会利用对象流这是为了后面解压的时候方便而考虑到的,不知道效果如何我们测试一把,测试代码如下:

     System.out.println("压缩文件测试~~~");
     String srcPath = "d://完整流程.png";
     String desPath = "d://完整流程.zip";
     zipFile(srcPath,desPath);
     System.out.println("压缩完毕----------")
    

    来看测试结果如下图所示:

    图片压缩测试结果图.png

    注意这个压缩完成之后不能用我们的常规解压工具开进行解压操作,需要我们自己来编写解压的算法来完成解压过程,上图我们发现解压的操作已经完成,那么我们先来总结下上述的思路流程:

    思路分析

    从代码的编写我们发现大致的思路是这样的

    • 首先我们读取源文件到一个字节数组中
    • 通过赫夫曼编码处理得到赫夫曼编码表
    • 最后完成压缩

    看完了压缩过程,我们直接来看解压过程

     /**
     *
     * @param zipSrcPath 待解压的文件路径
     * @param descFilePath 解压后文件所放的位置
     */
    public static void decodeFile(String zipSrcPath,String descFilePath){
        //定义文件输入流
        InputStream inputStream = null;
        //定义对象输入流
        ObjectInputStream objectInputStream = null;
        //定义文件的输出流
        OutputStream outputStream = null;
        try {
            //常见文件输入流
            inputStream = new FileInputStream(zipSrcPath);
            //创建一个和inputStream的对象输入流
            objectInputStream = new ObjectInputStream(inputStream);
            //读取byte数组中的赫夫曼编码huffmanBytes
            byte[] huffmanBytes = (byte[])objectInputStream.readObject();
            //读取赫夫曼编码表huffmanCodes
            Map<Byte,String> huffmanCodes = (Map<Byte, String>)objectInputStream.readObject();
            //解压
            byte[] bytes = decode(huffmanCodes, huffmanBytes);
            //将bytes写入到目的地址
            outputStream = new FileOutputStream(descFilePath);
            //将数据写入到descFilePath中
            outputStream.write(bytes);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
                objectInputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    这里就不在啰嗦了,直接看测试代码:

    String srcPath = "d://完整流程.zip";
    String descPath = "d://完整流程2.png";
     decodeFile(srcPath,descPath);
     System.out.println("解压完成!");
    

    来看测试结果:

    文件解压测试结果图.png

    最后解压发现跟原文件是一致的,亲测有效,图片打开没有受损,那么关于赫夫曼所有的学习到这就算结束了,完整代码请在git上看:

    相关文章

      网友评论

          本文标题:树结构入门教程-赫夫曼编码文件压缩

          本文链接:https://www.haomeiwen.com/subject/ywdquhtx.html