(算法课设)huffman编码 实现文件压缩和解压

如果这样看麻烦的话 点击我主页面 资源那 有这个哈夫曼编码代码的文件免费下载
import java.io.*;
import java.util.*;



class 哈夫曼编码 {
    static int last ;
    static HashMap huffmanTreeMapCode =new HashMap<>(); //哈夫曼编码表
    static StringBuilder stringBuilder =new StringBuilder();//字符串拼接类
    public static void main(String[] args) throws IOException, ClassNotFoundException {


            File file =new File("E:\\java\\Demo.txt"); //创建一个文件


            if(!file.exists()) //如果没有则创建
                file.createNewFile();
            File file1 =new File("E:/java/zipDemo.zip");
            if(!file.exists()) //如果没有则创建
                 file1.createNewFile();
            File file2 =new File("E:/java/unzip.txt");
            if(!file2.exists()) //如果没有则创建
                file.createNewFile();
            String srcFile ="E:/java/Demo.txt"; //原文件路径
            String zipFile ="E:/java/zipDemo.zip";//压缩后的文件路径
            String deZipFile ="E:/java/unzip.txt";//解压之后的文件路径
            zipFile(srcFile,zipFile); //压缩文件
            unZip(zipFile,deZipFile);//解压文件


    }
    public static void unZip(String zipFile,String dstFile) throws IOException, ClassNotFoundException//解压文件
    {
            FileInputStream fis =new FileInputStream(zipFile); //文件输入流
            byte[] bytes =new byte[fis.available()];  //创建一个byte数组大小为fis数据的长度
            fis.read(bytes); //将数据读取到bytes数组

           String s=Decode(bytes,huffmanTreeMapCode);//得到解码的字符串
            FileOutputStream fos =new FileOutputStream(dstFile);//文件输出流
            fos.write(s.getBytes());//将其写入到解压文件中
            fis.close();//关闭输入输出流
            fos.close();//关闭输入输出流
    }
    public static void zipFile(String srcFile,String dstFile) throws IOException //压缩文件
    {
       FileInputStream fis = new FileInputStream(srcFile); //创建文件输入流
       byte[] bytes =new byte[fis.available()];//创建一个byte数组大小为fis数据的长度
           fis.read(bytes);//将数据读取到bytes数组
       fis.close();//关闭输入输出流
       List list =getNode(new String(bytes)); //得到bytes数组对应的Node集合

        Node root =CreateHuffmanTree(list); //得到哈夫曼树的根结点
       getCode(root,"",stringBuilder);//得到huffman编码表 存入到了 开头的static HashMap huffmanTreeMapCode =new HashMap<>();
       byte[] b=zip(huffmanTreeMapCode,new String(bytes)); // 将byte数组经过哈夫曼编码后的编码再次转为byte数组
        System.out.println("huffman编码转为byte");
        for(byte bb:b)
        {
            System.out.print(bb+" ");
        }
        System.out.println();
        FileOutputStream fos = new FileOutputStream(dstFile);//创建文件输出流

        fos.write(b);//将其写入到压缩文件中
        fos.close();//关闭输入输出流
    }
  //第七步 对压缩成的byte数组进行解码
    public static String Decode(byte[] bytes,Map huffmanTreeMapCode )//解码  得到的是一个字符串
    {
             StringBuilder stringBuilder =new StringBuilder();
           /*  last =Integer.toBinaryString(bytes[bytes.length-1]).length(); *///判断最后一个byte数组的二进制位数是多少
             for(int i=0;i DecodeMap=new HashMap();  //创建一个字典
             for(char ch:huffmanTreeMapCode.keySet())//对huffman编码表进行遍历
             DecodeMap.put(huffmanTreeMapCode.get(ch),ch);//将huffman编码表的key作为键值存入新的字典 //键值作为key存入新的字典
             StringBuilder s =new StringBuilder();
             for(int i=0;i huffmanTreeMapCode,String s)//压缩 得到的是一个byte数组
    {   char []arr=s.toCharArray();//字符串转化为char数组
        StringBuilder stringBuilder =new StringBuilder();  //方便字符串拼接
        for(char ch:arr)//遍历char数组
        {
            stringBuilder.append(huffmanTreeMapCode.get(ch));//哈夫曼编码的key就是ch 键值就是哈夫曼编码表的编码
        }
        System.out.println("哈夫曼编码过后:");
        System.out.println(stringBuilder.toString());//此时得到的是哈夫曼编码 但其长度很长  将其转为byte
        int len =stringBuilder.length()%8==0?stringBuilder.length()/8:stringBuilder.length()/8+1; //byte 每8位一个 所以数组长度就是除8 如果有剩余就加1
        byte [] bytes =new byte[len];//压缩的byte数组
        last=stringBuilder.length()%8;
        String str = stringBuilder.toString();//将字符串拼接类转为字符串
        int index=0;//计步器
        for(int i=0;i getNode(String s)//计算一句话中的每个字母出现次数并将赋值到node里并装入到集合中
    {
        char[] arr =  s.toCharArray(); //将字符串转化为字符数组
        ArrayList arrayList=new ArrayList();//创建一个存 Node类型的集合
        Map nodesMap =new HashMap<>();//创建一个 key 为char,键值为int的字典
        for(char c:arr)//增强for遍历 字符数组
            if(!nodesMap.containsKey(c))//判断这个字典的key值是否有字符c
            {   //如果没有 就加入这个字符 并且指定键值为1
                nodesMap.put(c,1);
            }else nodesMap.put(c, nodesMap.get(c)+1);//如果有 则让键值加1
            for(char ch :nodesMap.keySet())//遍历字典的key
                arrayList.add(new Node(nodesMap.get(ch),ch));//加入结点 结点的权值就是 map的键值,字符就是字典的key值
        showListNode(arrayList);
        return arrayList;//返回装着结点的集合
    }
    //第三步得到创建哈夫曼树的根节点
    public static Node CreateHuffmanTree(List list){//创建哈夫曼树  返回树的根结点
          Collections.sort(list);//先按权值从小到大排序
        while(list.size()>1)// 一直循环到集合中只剩一个结点
        {
            Node leftNode =list.get(0);//左孩子为第一个结点
            Node rightNode=list.get(1);//右孩子为第二个结点
            Node parentNode=new Node(leftNode.weight+rightNode.weight,'\0');//父亲结点的权值为左孩子和右孩子的权值之和,字符为空
            parentNode.left=leftNode;//父母的左孩子为leftnode
            parentNode.right=rightNode;//父母的右孩子为rightnode
            list.remove(leftNode);//删除第一小的结点
            list.remove(rightNode);//删除第二小的结点
            list.add(parentNode);//加入父亲结点
            Collections.sort(list);//再次排序
        }
        if(list.size()==0)
        {
           try {

               throw new RuntimeException();
           }catch (Exception e)
           {
               System.out.println("根节点为空,请在被压缩文件中添加内容");
           }
        }

        return list.get(0);//集合中只有一个结点,返回的第一个结点就是根结点


    }
    public static void preOrder(Node root)//树的前序遍历
    {
        System.out.println(root);
        if(root.left!=null)
            preOrder(root.left);
        if(root.right!=null)
            preOrder(root.right);
    }
    public static void showListNode(List list)
    {
        for(Node node:list)
        {
            System.out.println(node);
        }
    }
    }
//第一步创建结点类
class Node implements Comparable {
    int weight;//权值
    char english;//字符
    Node left;//左孩子
    Node right;//右孩子
    public Node(int weight, char english)
    {
        this.weight=weight;
        this.english=english;
    }


    @Override
    public String toString() {
        return "Node{" +
                " 字符=" + english +
                ",权重=" + weight +
                '}' ;
    }

    @Override
    public int compareTo(Node o) {
        return this.weight-o.weight;
    }//自定义排序
}

原文件数据长度8001 (算法课设)huffman编码 实现文件压缩和解压_第1张图片

压缩后文件数据长度3396 (算法课设)huffman编码 实现文件压缩和解压_第2张图片

还原文件数据长度8001 (算法课设)huffman编码 实现文件压缩和解压_第3张图片

 

 

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