package com.example.demo.code50;
import java.io.*;
import java.util.*;
/**
* @author ming
* @create 2022/5/31
* @description:
*/
public class HuffmanCode {
private static Map<String,Object> mapGlobal = new HashMap<String,Object>();
static class Node implements Comparable<Node> {
Byte data;
int weight;
Node left;
Node right;
public Node(Byte data,int weight) {
this.data = data;
this.weight = weight;
}
@Override
public String toString() {
return "Node{" +
"data=" + data +
", weight=" + weight +
'}';
}
@Override
public int compareTo(Node o) {
return this.weight-o.weight;
}
}
public static Node createHuffmanTree(String Str){
byte[] array = Str.getBytes();
List<Node> nodes = new ArrayList<Node>();
//[node={'a',6},node={'b',9}]
int len = array.length;
for (int i = 0; i < len; i++) {
Node temp = null;
for (Node node : nodes) {
if (node.data == array[i]) {
temp = node;
}
}
if(temp != null){
Node node = new Node(temp.data, temp.weight + 1);
nodes.remove(temp);
nodes.add(node);
}else{
Node node = new Node(array[i], 1);
nodes.add(node);
}
}
//根据list创建哈夫曼树
while(nodes.size()>1){
Collections.sort(nodes);
Node leftChild = nodes.get(0);
Node rightChild = nodes.get(1);
Node pareNode = new Node( null,leftChild.weight + rightChild.weight);
pareNode.left = leftChild;;
pareNode.right = rightChild;
nodes.remove(leftChild);
nodes.remove(rightChild);
nodes.add(pareNode);
}
return nodes.get(0);
}
public static Map<Byte,String> getCode(Node node){
Map<Byte,String> map = new HashMap<Byte,String>();
StringBuilder sb = new StringBuilder();
return createHuffmanCode(map,sb,node);
}
public static Map<Byte,String> createHuffmanCode(Map<Byte,String> map,StringBuilder sb,Node node){
//map<Byte,String> 32-01
if(node == null) return map ;
if(node.left!=null){
sb.append(1);
createHuffmanCode(map,sb,node.left);
//回溯会添加上次的字符串编码
sb.replace(sb.length() - 1, sb.length(), "");
}
if(node.right!=null){
sb.append(0);
createHuffmanCode(map,sb,node.right);
sb.replace(sb.length() - 1, sb.length(), "");
}
map.put(node.data,sb.toString());
sb=new StringBuilder();
return map;
}
public static void showPre(Node node){
if(node==null) return ;
System.out.println(node);
showPre(node.left);
showPre(node.right);
}
public static Map<String,Object> zip(String str) throws IOException {
byte[] bytes = str.getBytes();
Node node = createHuffmanTree(str);
Map<Byte, String> huffmanCode = getCode(node);
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
sb.append(huffmanCode.get(aByte));
}
//11000000
//计算发送数组的长度
System.out.println(sb);
int len = (sb.length()+7)/8;
byte[] sendByte = new byte[len];
String temp = "";
int index = 0;
for (int i = 0; i < len; i++) {
if(index+8>sb.length()){
temp = sb.substring(index);
}else{
temp = sb.substring(index,index+8);
}
sendByte[i] = (byte) Integer.parseInt(temp,2);
index = index + 8;
}
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File("D:\\Desktop\\ming.zip")));
HashMap<String,Object> tempMap = new HashMap<String,Object>();
try {
out.write(sendByte,0,sendByte.length);
tempMap.put("byteArray",sendByte);
tempMap.put("len",sb.length());
tempMap.put("code",huffmanCode);
return tempMap;
} catch (IOException e) {
e.printStackTrace();
}finally{
out.close();
return tempMap;
}
}
public static String toBinary(byte num,boolean flag) {
int n = num;
if(flag){
n = n|256;
}
String s = Integer.toBinaryString(n);
if(flag){
return s.substring(s.length()-8);
}else{
return s;
}
}
public static void unZip(Map<Byte,String> map,byte[] bytes,int len){
int last = 0;
StringBuilder sb = new StringBuilder();
boolean flag = true;
for (int i = 0; i < bytes.length; i++) {
if(i==bytes.length-1) {
StringBuilder builderString = new StringBuilder();
flag = false;
last = len-sb.length();
String s = toBinary(bytes[i], flag);
last = last - s.length();
while(last>0){
builderString.append("0");
last--;
}
builderString.append(s);
sb.append(builderString.toString());
}else{
String s = toBinary(bytes[i], flag);
sb.append(s);
}
}
System.out.println(sb);
//32-10 反转 10-32
Map<String,Byte> reverseHuffman = new HashMap<String,Byte>();
for (Byte aByte : map.keySet()) {
String value = map.get(aByte);
reverseHuffman.put(value,aByte);
}
List<Byte> list = new ArrayList<Byte>();
String tempStr = "";
for (int i = 0; i < sb.length(); i++) {
tempStr =tempStr + sb.charAt(i) +"";
if(reverseHuffman.containsKey(tempStr)){
list.add(reverseHuffman.get(tempStr));
tempStr = "";
}
}
byte[] byteArray = new byte[list.size()];
for (int i = 0; i < list.size(); i++) {
byteArray[i] = list.get(i);
}
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(new File("D:\\Desktop\\ming2.txt")));
out.write(byteArray,0,byteArray.length);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//文件压缩
public static void zipFile(){
BufferedReader reader = null;
String str ="";
try {
File file = new File("D:\\Desktop\\ming.txt");
reader = new BufferedReader(new FileReader(file));
str = str + reader.readLine();
mapGlobal = zip(str);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void unZipFile(){
byte[] byteArray = (byte[]) mapGlobal.get("byteArray");
int len = (int) mapGlobal.get("len");
Map<Byte,String> huffmanCode = (Map<Byte, String>) mapGlobal.get("code");
unZip(huffmanCode, byteArray, len);
}
public static void main(String[] args) throws IOException {
zipFile();
unZipFile();
}
}
利用哈夫曼树进行文件压缩与解压
最新推荐文章于 2023-06-18 19:15:44 发布