(二)实现文本压缩_java

通过java来实现文本压缩需要以下几个步骤:
1.创建二叉树
2.根据给定的字符串内容(读取文本文件),统计每个字符出现的频率,创建对应的节点
3.根据节点的权值创建哈夫曼树,统计字符编码
4.把字符数据替换成对应的编码
5.把字符编码没每8个一组转成byte写入文件
6.把码表写入文件
7.添加图形化界面

二.根据给定的字符串内容(读取文本文件),统计每个字符出现的频率,创建对应的节点

//读取文本数据
    public String readFile(String path){
        System.out.println("readFile_读取文件");
        File file =new File(path);//将文件封装为File类对象
        FileReader fr;
        String dataStr="";
        try{
            fr=new FileReader(file);//创建FileReader对象
            BufferedReader br =new BufferedReader(fr);
            String s="";
            while((s=br.readLine())!=null){
                dataStr+=s;
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return dataStr;
    }

首先通过BufferedReader读取文件内容,将文件中的字符保存到dataStr中返回

3.根据节点的权值创建哈夫曼树,统计字符编码

//统计字符频率
    public void number(String dataStr){
        System.out.println("统计字符频率");
        hm=new HashMap<>();
        for (int i = 0; i < dataStr.length(); i++) {
            if (!hm.containsKey(dataStr.charAt(i)+"")){//判断该key值是否在表中存在
                //添加当前字符到哈希表中
                hm.put(dataStr.charAt(i)+"",1);
            } else{
                hm.put(dataStr.charAt(i)+"",hm.get(dataStr.charAt(i)+"")+1);
            }
        }
        //根据字符数据创建结点
        for(String s:hm.keySet()){
           TreeNode node =new TreeNode(hm.get(s),s);
            listNode.add(node);
        }
    }

通过for循环在dataStr中遍历数组,统计每个字符出现的频率,因为哈希表中是<String,Integer>类型的,dataStr.charAt(i)是每个字符,所以要将char字符类型转换为String字符串类型,才能存储到哈希表中。

4.把字符数据替换成对应的编码

//统计叶子节点的哈夫曼编码
    public void setCode(TreeNode root){
        if(root.left != null) {
            root.left.code = root.code + "0";
            setCode(root.left);
        }
        if(root.right != null) {
            root.right.code = root.code + "1";
            setCode(root.right);
        }
    }

给二叉树上的节点创建相应编码,向左为0,向右为1;

 //打印叶子节点
    public void inorder(TreeNode root){
        if(root!=null){
            inorder(root.left);
            //判断是否是叶子结点
            if (root.left==null&&root.right==null){
                System.out.println(root.c+"  data= "+root.data+"  code= "+root.code);//data字符出现频率 code字符编码
                hashMap.put(root.c,root.code);
            }
            inorder(root.right);//向后遍历数据字符
        }
    }

按照中序遍历打印叶子结点,并经将字符和编码存入到哈希表当中,

  //把字符数据替换成对应编码
    public String setCoding(String dataStr){
        System.out.println("字符替换编码");
        //把字符编码转成byte写入文件
        StringBuilder stringBuilder=new StringBuilder();
        for (int i=0;i<dataStr.length();i++){
            stringBuilder.append(codingMap.get(dataStr.charAt(i)+""));//取出码表中字符对应编码
        }
        return stringBuilder.toString();//转化为String类型,返回编码
    }

将字符数据替换成相应编码,通过取出表中对应字符来返回编码

5.把字符编码没每8个一组转成byte写入文件

 //把字符的编码数据转成byte写入文件
    public void writeData(String codingStr) {
        System.out.println("将字符编码转成byte写入文件");
        try {
            FileOutputStream fos = new FileOutputStream(("File\\compress.txt"));
            int dataNum = codingStr.length()/8;//合成字节数
            int last =codingStr.length()%8;//不足8位,剩余要补足的数
            int len=8;
            int data=0;
            for (int j = 0; j < dataNum; j++) {
                for (int i = 0; i < len; i++) {
                    //从j*len开始的len*(j+1))个字符
                    data=Integer.parseInt(codingStr.substring(j*len,len*(j+1)),2);
                }
                fos.write(data);
                fos.flush();
            }
            String s1="";
            for (int i = 0; i < 8 - last; i++) {
                s1+="0";
            }
            String lastStr=codingStr.substring(dataNum*8,dataNum*8+last)+s1;
            byte ls=(byte)Integer.parseInt(lastStr,2);
            fos.write(ls);
            //最后补位
            fos.write(8-last);
            fos.flush();

            System.out.println("写文件成功!");
        } catch (Exception e) {
            e.printStackTrace();//指出异常的类型、性质、栈层次及出现在程序中的位置。
        }
    }

将字符编码写入到新文件当中,判断编码位数,如果编码不足8位,向后用0补全8位

最后合并方法就能够实现文本压缩功能

public void compress(String path){
        String dataStr=readFile(path);//读取文件
        System.out.println("dataStr:"+dataStr);
        number(dataStr);
        TreeNode root=createTree(listNode);
        setCode(root);
        inorder(root);
        String dataCoding=setCoding(dataStr);
        System.out.println("dataCoding:"+dataCoding);
        writeData(dataCoding);
    }

效果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值