1,解压数据还是需要之前的代码 就不在做解释吧之前代码拷过来就好
class Node implements Comparable<Node> {
Byte data;
int weight;
Node left;
Node right;
public Node(Byte data, int weight) {
super();
this.data = data;
this.weight = weight;
}
@Override
public int compareTo(Node o) {
// TODO Auto-generated method stub
return this.weight - o.weight;
}
@Override
public String toString() {
return "Node [data=" + data + ", weight=" + weight + "]";
}
public void preOrder() {
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
}
if (this.right != null) {
this.right.preOrder();
}
}
}
重点讲解decode这个方法
public class HuffmanCode {
public static void main(String[] args) {
String str = "i like like like java do you like a java";
byte[] bytes = str.getBytes();
byte[] huffmanCodesBytes = huffmanZip(bytes);
byte[] sourceBytes = decode(huffmanCodes, huffmanCodesBytes);
System.out.println(new String(sourceBytes));
}
//首先传值先传需要解压的字节数组,还有一个map(怎么把之前字节转化成字节的数字字符的)
private static byte[] decode(Map<Byte, String> huffmanCodes, byte[] huffmanBytes) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < huffmanBytes.length; i++) {
//就是判断是不是最后一个字节 如果是就放false不是就是true
boolean flag = (i == huffmanBytes.length - 1);
String str = byteToBitString(!flag, huffmanBytes[i]);
//都放在字符流里
stringBuilder.append(str);
}
//然后吧传进来的map key和value颠倒 这样在getkey直接获取到对应的字节
Map<String, Byte> map = new HashMap<>();
for (Map.Entry<Byte, String> entry : huffmanCodes.entrySet()) {
map.put(entry.getValue(), entry.getKey());
}
List<Byte> list = new ArrayList<>();
for (int i = 0; i < stringBuilder.length(); i = i) {
int count = 1;
boolean flag = true;
Byte b = null;
//不断遍历
while (flag) {
//在字符流从0到1++去获取字符串
String key = stringBuilder.substring(i, i + count);
//用字符串在map获取值看能不能获取 获取不到就一直加count如果获取到了
//就false结束循环
b = map.get(key);
if (b == null) {
count++;
} else {
flag = false;
}
}
//把获取到的值放进list里
list.add(b);
i += count;
}
//把list里的数字放在byte数组他就自动转化成字母了
byte[] b = new byte[list.size()];
for (int i = 0; i < b.length; i++) {
b[i] = list.get(i);
}
return b;
}
//怎么把字节数组里的数字转化成二进制 ,flag只判断是不是数组的最后一个字节
private static String byteToBitString(boolean flag, byte b) {
//这里运用到了二进制的知识 不太懂怎么解码的反正----有待学习
int temp = b;
if (flag) {
temp |= 256;
}
String str = Integer.toBinaryString(temp);
if (flag) {
return str.substring(str.length() - 8);
} else {
return str;
}
}
private static byte[] huffmanZip(byte[] bytes) {
List<Node> list = getNodes(bytes);
Node node = createHuffmanTree(list);
Map<Byte, String> huffmanCodes = getCodes(node);
byte[] zip = zip(bytes, huffmanCodes);
return zip;
}
private static byte[] zip(byte[] bytes, Map<Byte, String> huffmanCodes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
sb.append(huffmanCodes.get(bytes[i]));
}
int len;
if (sb.length() % 8 == 0) {
len = sb.length() / 8;
} else {
len = sb.length() / 8 + 1;
}
byte[] huffmanCodeBytes = new byte[len];
int index = 0;
for (int i = 0; i < sb.length(); i += 8) {
String strByte;
if (i + 8 > sb.length()) {
strByte = sb.substring(i);
} else {
strByte = sb.substring(i, i + 8);
}
huffmanCodeBytes[index] = (byte) Integer.parseInt(strByte, 2);
index++;
}
return huffmanCodeBytes;
}
static Map<Byte, String> huffmanCodes = new HashMap<>();
static StringBuilder stringBuilder = new StringBuilder();
private static Map<Byte, String> getCodes(Node root) {
if (root == null) {
return null;
}
getCodes(root.left, "0", stringBuilder);
getCodes(root.right, "1", stringBuilder);
return huffmanCodes;
}
private static void getCodes(Node node, String code, StringBuilder stringBuilder) {
StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);
stringBuilder2.append(code);
if (node != null) {
if (node.data == null) {
getCodes(node.left, "0", stringBuilder2);
getCodes(node.right, "1", stringBuilder2);
} else {
huffmanCodes.put(node.data, stringBuilder2.toString());
}
}
}
private static List<Node> getNodes(byte[] bytes) {
ArrayList<Node> nodes = new ArrayList<Node>();
Map<Byte, Integer> counts = new HashMap<>();
for (byte b : bytes) {
Integer count = counts.get(b);
if (count == null) {
counts.put(b, 1);
} else {
count++;
counts.put(b, count);
}
}
for (Map.Entry<Byte, Integer> entry : counts.entrySet()) {
nodes.add(new Node(entry.getKey(), entry.getValue()));
}
return nodes;
}
private static Node createHuffmanTree(List<Node> nodes) {
while (nodes.size() > 1) {
Collections.sort(nodes);
Node left = nodes.remove(0);
Node right = nodes.remove(0);
Node parent = new Node(null, left.weight + right.weight);
nodes.add(parent);
parent.left = left;
parent.right = right;
}
return nodes.get(0);
}
public static void preOrder(Node root) {
if (root != null) {
root.preOrder();
} else {
System.out.println("空数组");
}
}
}
这里解码相对比较容易一些除了那些二进制的问题
还是那就看懂了代码的实现
明天继续文件解码 奥利给