哈夫曼编码解码

哈夫曼编码解码

zip

  1. 将 String 的原始字节数组转换成哈夫曼编码处理后的字节数组
  2. 通过 哈夫曼编码表 获取 byte 对应的 value
  3. 步长为 8 对StringBuffer进行分割,最后一位不满8位则直接存储
  4. 通过 Integer.parseInt( , 2) 进行转换

byteToBinaryString

  1. 通过传入 byte 字节 和 是否为 最后一位 flag
  2. temp |= 256 补高位

decode

  1. 哈夫曼解码
  2. 传入 哈夫曼编码处理后的 字节数组、哈夫曼编码表
  3. 原始字节数组字符串拼接
  4. codeMap 哈夫曼编码表 反转
  5. 步长为 8 对 sb 进行解析、解析出的 Byte temp 存入 List<Byte>
    public static void main(String[] args) {
    
    
        // 数据压缩
        String str = "i like like like java do you like a java";

        List<hufNode> nodes = strToList(str);

        hufNode root = createHufmanTree(nodes);

        getCodes(root, "", context);
        
        byte[] bytes = str.getBytes();
        byte[] zip = zip(bytes, codeMap);
        System.out.println(Arrays.toString(zip));


        byte[] decode = decode(codeMap, zip);
        System.out.println(new String(decode));

    }





    /**
     * 将原始的字节数组转换成哈夫曼编码处理后的字节数组
     *
     * @param bytes 原始的字节数组
     * @return 哈夫曼编码处理后的字节数组
     */
    public static byte[] zip(byte[] bytes, Map<Byte, String> codeMap) {
    
    
        StringBuffer sb = new StringBuffer();
        for (byte b : bytes) {
    
    
            // 拼接到 sb 中
            sb.append(codeMap.get(b));
        }
        int len = 0;
        // 步长 8 位截取转换
        if (sb.length() % 8 == 0) {
    
    
            len = sb.length() / 8;
        } else {
    
    
            len = sb.length() / 8 + 1;
        }
        // 等价于
//        len = (sb.length() + 7) / 8;
        byte[] res = new byte[len];
        int index = 0;
        for (int i = 0; i < sb.length(); i = i + 8) {
    
    
            String strByte;
            if (i + 8 > sb.length()) {
    
    
                // 最后一个不够 8 位
                strByte = sb.substring(i);
            } else {
    
    
                strByte = sb.substring(i, i + 8);  // 截取8位
            }
            // 按二进制转换成int
            res[index++] = (byte) Integer.parseInt(strByte, 2);
        }

        return res;
    }


    /**
     *  解压:
     *     根据哈夫曼编码表解压回字符串
     * @param codeMap
     * @param bytes  编码处理后的字节数组
     */
    public static byte[] decode(Map<Byte, String> codeMap, byte[] bytes) {
    
    
        StringBuffer sb = new StringBuffer();

        // 原始字节数组字符串拼接
        for (int i = 0 ; i < bytes.length ; i++){
    
    
            boolean flag = (i == bytes.length - 1);
            String str = byteToStringBuffer(bytes[i], flag);
            //
            sb.append(str);
        }

        Map<String, Byte> map = new HashMap<>();
        // 反转
        for (Map.Entry<Byte , String> e : codeMap.entrySet()){
    
    
            map.put(e.getValue(), e.getKey());
        }

        List<Byte> list = new ArrayList<>();
        // 解释
        for (int i = 0; i < sb.length() ; ){
    
    
            int count = 1;
            while(true){
    
    
                Byte temp = map.get(sb.substring(i, i + count));
                if(temp == null){
    
    
                    count++;
                } else {
    
    
                    list.add(temp);
                    break ;
                }
            }
            i = i + count;
        }

        // 换回 byte 数组
        byte[] res = new byte[list.size()];
        for (int i = 0 ; i < res.length ; i++){
    
    
            res[i] = list.get(i);
        }

        return res;
    }


    /**
     * 将压缩的哈夫曼编码处理后的字节数组 转换成 原始的字节数组
     *
     * @param b 传入的 byte
     * @param flag  判断是否需要补高位
     * @return 该 b 的对应的二进制字符串(补码的形式返回)
     */
    public static String byteToStringBuffer(byte b, boolean flag) {
    
    
        int temp;
        temp = b;
        if (!flag) {
    
    
            // 补高位
            temp |= 256;
        }
        String str = Integer.toBinaryString(temp);
        if (flag) {
    
    
            return str;
        } else {
    
    
            return str.substring(str.length() - 8); // 返回后8 位
        }
    }


猜你喜欢

转载自blog.csdn.net/qq_43765535/article/details/107690039