1、实现的压缩工具类
package com.cn.test.tree.zip;
import java.util.*;
/**
* 压缩工具类
*/
public class ZipUtil {
public static Map huffCodes = new HashMap<>();
public static Map reverseHuffCodes = new HashMap<>();
/**
* 普通字符串压缩
* @param source
* @return
*/
public static byte[] zipString(String source){
if(source==null){
return null;
}
System.out.println("原始字符串:"+source);
//构建哈夫曼树列表
byte[] bytes = source.getBytes();
System.out.println("原始字节长度:"+bytes.length);
//构建哈夫曼村
HuffTree huffTree = new HuffTree();
huffTree.buildTree(bytes);
huffTree.obtainHuffCodes(huffTree.getRoot(),"",huffCodes);
//生成压缩后的字符串二进制数
StringBuilder binaryBuilder = new StringBuilder();
for (byte b:bytes){
binaryBuilder.append(huffCodes.get((int)b));
}
String strBinary= binaryBuilder.toString();
System.out.println("字符串二进制数:"+strBinary);
//把字符二进制数转换成真实的二进制数
int len = (strBinary.length()+7)/8;
byte[] result = new byte[len+1];
//byte[0]留出来,如果结尾补了位,把补位的数字放在这里
int index = 1;
for (int i = 0 ;i =strBinary.length()){
String last = strBinary.substring(i);
//补位,使其正好是8位
last += "00000000".substring(8-(i+8-strBinary.length()));
result[index++] = (byte)Integer.parseInt(last,2);
result[0] = (byte)(i+8-strBinary.length());
break;
}else{
result[index++] = (byte)Integer.parseInt(strBinary.substring(i,i+8),2);
i+=8;
}
}
return result;
}
/**
* 将二进制,转换成字符串二进制
* @param b
* @return
*/
public static String byte2Str(byte b){
String s = Integer.toBinaryString(b);
if(s.length()>8){
s = s.substring(s.length()-8);
}
if(s.length()<8){
s = String.format("%08d", Integer.parseInt(s));
}
return s;
}
/**
* 解压字符串
* @param zipBytes
* @return
*/
public static String unZip(byte[] zipBytes){
//解压之后的字符串
StringBuilder unZipBinaryBuilder = new StringBuilder();
for (int i = 1 ;i0){
unZipBinary = unZipBinary.substring(0,unZipBinary.length()-buWei);
}
System.out.println("解压之后的字符串二进制数:"+unZipBinary);
for (Map.Entry entry:huffCodes.entrySet()){
reverseHuffCodes.put(entry.getValue(),entry.getKey());
}
List source = new ArrayList<>();
int j = 0;
for (int i = 0 ; j
执行这个工具的结果是:
原始字符串:Notice on Registration for Internationa Dear international students, According to the scho
原始字节长度:90
字符串二进制数:000110001100110111101110001100101001100011111001111101101111101001011101010011010010100110000100011011011000011010100110010110101010100110100101010100110000011100101010110111101010100110010110101010100110100101010100001000111111010011100011100111000101001111000010101100000011101111010011011111001110101011111001110000101110011111111000111111011101111111001
压缩后的字节长度:46
解压之后的字符串二进制数:000110001100110111101110001100101001100011111001111101101111101001011101010011010010100110000100011011011000011010100110010110101010100110100101010100110000011100101010110111101010100110010110101010100110100101010100001000111111010011100011100111000101001111000010101100000011101111010011011111001110101011111001110000101110011111111000111111011101111111001
解压之后的字符串:Notice on Registration for Internationa Dear international students, According to the scho
通过这个结果可以看来把字符串从90个字节的长度,压缩到了46个字节,也能够正常解压
2、定义的树的节点
package com.cn.test.tree.zip;
/**
* hufftree的树节点
*/
public class HuffTreeNode implements Comparable{
//字符值
private Integer value;
//出现的次数
private Integer weight;
//左节点
private HuffTreeNode leftNode;
//右节点
private HuffTreeNode rightNode;
public HuffTreeNode(Integer value, Integer weight) {
this.value = value;
this.weight = weight;
}
public HuffTreeNode(Integer value, Integer weight,Integer weight2) {
this.value = value;
if(weight==null){
weight = 0;
}
if(weight2 == null){
weight2 = 0;
}
this.weight = weight+weight2;
}
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public HuffTreeNode getLeftNode() {
return leftNode;
}
public void setLeftNode(HuffTreeNode leftNode) {
this.leftNode = leftNode;
}
public HuffTreeNode getRightNode() {
return rightNode;
}
public void setRightNode(HuffTreeNode rightNode) {
this.rightNode = rightNode;
}
@Override
public String toString() {
return "HuffTreeNode{" +
"value=" + value +
", weight=" + weight +
'}';
}
@Override
public int compareTo(HuffTreeNode o) {
return this.weight - o.weight;
}
}
3、定义的树
package com.cn.test.tree.zip;
import java.util.*;
/**
* 哈夫曼树
*/
public class HuffTree {
private HuffTreeNode root;
/**
* 哈夫曼树的具体构建
* @param nodes
* @return
*/
private HuffTreeNode HalfManTree(List nodes){
if(nodes == null){
return null;
}
while (nodes.size()>1){
Collections.sort(nodes);
HuffTreeNode leftNode = nodes.get(0);
HuffTreeNode rightNode = nodes.get(1);
HuffTreeNode parentNode = new HuffTreeNode(null,leftNode.getWeight(),rightNode.getWeight());
parentNode.setLeftNode(leftNode);
parentNode.setRightNode(rightNode);
nodes.remove(0);
nodes.remove(0);
nodes.add(parentNode);
}
return nodes.get(0);
}
/**
* 获取每一个元素的路径编码
* 向左是0,右是1
* @param huffTreeNode
*/
public void obtainHuffCodes(HuffTreeNode huffTreeNode, String route, Map huffCodes){
if(huffTreeNode == null){
return;
}
if(huffTreeNode.getRightNode() == null && huffTreeNode.getLeftNode() == null){
huffCodes.put(huffTreeNode.getValue(),route);
}
if(huffTreeNode.getLeftNode()!=null){
obtainHuffCodes(huffTreeNode.getLeftNode(),route+"0",huffCodes);
}
if(huffTreeNode.getRightNode()!=null){
obtainHuffCodes(huffTreeNode.getRightNode(),route+"1",huffCodes);
}
}
public HuffTreeNode getRoot() {
return root;
}
public void setRoot(HuffTreeNode root) {
this.root = root;
}
/**
* 构建哈夫曼树
* @param bytes
*/
public void buildTree(byte[] bytes) {
//TODO 初始化大小待定,后续可以优化
Map weightMap = new HashMap<>();
for (byte b:bytes){
int key = (int)b;
if(weightMap.get(key) == null){
weightMap.put(key,1);
}else{
weightMap.put(key,weightMap.get(key)+1);
}
}
List nodeList = new ArrayList<>(weightMap.size());
for (Map.Entry entry :weightMap.entrySet()){
nodeList.add(new HuffTreeNode(entry.getKey(),entry.getValue()));
}
this.setRoot(HalfManTree(nodeList));
}
}