Java哈夫曼树与文件压缩和解压缩

之前看到一篇文章,博主给出了压缩文件:https://blog.csdn.net/bluesky_usc/article/details/54185106

在这基础上,添加了对文件进行了解压的方法:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.*;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.LinkedList;

public class Main {

    public static void main(String[] args) throws Exception {
        //创建压缩对象
        Compress compress = new Compress();
        //统计文件中0-255出现的次数
        compress.countTimes("F:\\test.txt");
        //构造哈夫曼树,并得到根节点
        HuffmNode root=compress.createTree();
        //得到哈夫曼编码
        compress.getHuffmCode(root, "");
        //压缩文件
        compress.compress("F:\\test.txt",
                "F:\\test.zip");
        compress.Decode("F:\\test.zip" , root);        //解压
        System.out.println(Compress.breath(root));
    }
}



/****/

 class HuffmNode {
    //数据域
    private int data;
    //索引
    private int index;
    //左子节点
    private HuffmNode left;
    //右子节点
    private HuffmNode right;

    //哈夫曼节点的构造函数
    public HuffmNode(int data,int index){
        this.data=data;
        this.index=index;
    }

    //私有属性的封装
    public int getData() {
        return data;
    }
    public void setData(int data) {
        this.data = data;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
    public HuffmNode getLeft() {
        return left;
    }
    public void setLeft(HuffmNode left) {
        this.left = left;
    }
    public HuffmNode getRight() {
        return right;
    }
    public void setRight(HuffmNode right) {
        this.right = right;
    }


    public String toString() {
        // TODO Auto-generated method stub
        int num = 0;
        if(index != -1)
            return "data:" + ((char)this.getIndex()+"") + ",weight:" + this.getData() + ";   ";

        return "data:" + ((char)this.getIndex()+"") + ",weight:" + this.getData()+ ";   ";
    }

}


class Compress {

    public static int [] times = new int[256];
    public String [] HuffmCodes=new String[256];
    public LinkedList list = new LinkedList();
    //统计次数

    //初始化
    public Compress(){
        for (int i = 0; i < HuffmCodes.length; i++) {
            HuffmCodes[i]="";
        }
    }

    public void countTimes(String path) throws Exception{
        //构造文件输入流
        FileInputStream fis = new FileInputStream(path);
        //读取文件
        int value=fis.read();
        while(value!=-1){
            times[value]++;
            value=fis.read();
        }
        //关闭流
        fis.close();
    }

    //构造哈夫曼树
    public HuffmNode createTree(){
        //将次数作为权值构造森林
        for (int i = 0; i < times.length; i++) {
            if(times[i]!=0){
                HuffmNode node = new HuffmNode(times[i],i);
                //将构造好的节点加入到容器中的正确位置
                list.add(getIndex(node), node);
            }
        }

        //将森林(容器中的各个节点)构造成哈夫曼树
        while(list.size()>1) {
            //获取容器中第一个元素(权值最小的节点)
            HuffmNode firstNode =list.removeFirst();
            //获取中新的第一个元素,原来的第一个元素已经被移除了(权值次小的节点)
            HuffmNode secondNode =list.removeFirst();
            //将权值最小的两个节点构造成父节点
            HuffmNode fatherNode =
                    new HuffmNode(firstNode.getData()+secondNode.getData(),-1);
            fatherNode.setLeft(firstNode);
            fatherNode.setRight(secondNode);
            //父节点加入到容器中的正确位置
            list.add(getIndex(fatherNode),fatherNode);
        }
        //返回整颗树的根节点
        return list.getFirst();
    }
    //利用前序遍历获取编码表
    public void getHuffmCode(HuffmNode root,String code){
        //往左走,哈夫曼编码加0
        if(root.getLeft()!=null){
            getHuffmCode(root.getLeft(),code+"0");
        }
        //往右走,哈夫曼编码加1
        if(root.getRight()!=null){
            getHuffmCode(root.getRight(),code+"1");
        }
        //如果是叶子节点,返回该叶子节点的哈夫曼编码
        if(root.getLeft()==null && root.getRight()==null){
//          System.out.println(root.getIndex()+"的编码为:"+code);
            HuffmCodes[root.getIndex()]=code;
        }
    }

    //压缩文件
    public void compress(String path,String destpath) throws Exception{



        //构建文件输出流
        FileOutputStream fos = new FileOutputStream(destpath);
        FileInputStream fis = new FileInputStream(path);

        /**===============将数据写入到文件中================*/

        //读文件,并将对应的哈夫曼编码串接成字符串
        int value=fis.read();
        String str = "";
        while(value!=-1){
            str+=HuffmCodes[value];
//          System.out.println((char)value+":"+str);
            value=fis.read();
        }
        System.out.println(str);
        fis.close();

        String s="";
        while(str.length()>=8){
            s=str.substring(0, 8);
            int b=changeStringToInt(s);
//              System.out.println(c);
            fos.write(b);
            fos.flush();
            str=str.substring(8);
        }

        int last1=8-str.length();
        for (int i = 0; i  0){
            while(true) {
                if ((int) (str.charAt(num) - 48) == 0) {
                    node = last_node.getLeft();
                    if(node == null){ break;}
                }
                if ((int) (str.charAt(num) - 48) == 1) {
                    node = last_node.getRight();
                    if(node == null){ break;}
                }
                last_node = node;
                num++;
                if(num > str.length() - 1)
                    break;
            }
            os += ((char)last_node.getIndex() + "");
            str = str.substring(num);
            num = 0;
            last_node = root;
        }
        System.out.println(os);
    }


    public static String addZeroForNum(String str,int strLength) {
        int strLen =str.length();
        if (strLen  List breath(HuffmNode root) {
        List list = new ArrayList();
        Queue queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            HuffmNode pNode = queue.poll();
            list.add(pNode);
            if (pNode.getLeft() != null) {
                queue.add(pNode.getLeft());
            }
            if (pNode.getRight() != null) {
                queue.add(pNode.getRight());
            }
        }
        return list;
    }
}

你可能感兴趣的:(算法,java)