//huffman树节点类
class HCNode implements Comparable<HCNode>{
Byte data; //数据(字符)
int weight; //权重(字符出现次数)
HCNode left;
HCNode right;
public HCNode(Byte data,int weight){
this.data=data;
this.weight=weight;
}
@Override
public int compareTo(HCNode o) {
return weight-o.weight;
}
@Override
public String toString() {
return "HCNode{" +
"data=" + data +
", weight=" + weight +
'}';
}
}
//简单写了
//解压文件
public static void unZipFile(String zipFile,String dst)throws IOException,ClassNotFoundException{
ObjectInputStream in=new ObjectInputStream(new FileInputStream(zipFile));
FileOutputStream out=new FileOutputStream(dst);
byte[] zipDatas=(byte[]) in.readObject();
Map<Byte,String> huffmanEn= (Map<Byte, String>) in.readObject();
byte[] datas=decode(zipDatas,huffmanEn);
out.write(datas);
System.out.println("解压成功");
}
//压缩文件
public static void zipFile(String src,String dst){
FileInputStream in=null;
ObjectOutputStream out=null;
try {
in=new FileInputStream(src);
out=new ObjectOutputStream(new FileOutputStream(dst));
byte[] datas=new byte[in.available()];
in.read(datas);
byte[] zipDatas=huffmanZip(datas);
out.writeObject(zipDatas);
out.writeObject(encodingTable);
System.out.println("压缩成功");
}catch (IOException e){
e.printStackTrace();
}finally {
if(in!=null){
try {
in.close();
}catch (IOException e){
e.printStackTrace();
}
}
if(out!=null){
try {
out.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
public static Map<Byte,String> encodingTable=new HashMap<>(); //huffman编码表
public static String last; //记录原数据经过编码后得到的二进制串中最后不足八位的串
//arr 要压缩的字节数据
//将arr转为Huffman树的叶子节点的集合
public static List<HCNode> getNodes(byte[] arr){
List<HCNode> nodes=new ArrayList<>();
Map<Byte,Integer> map=new HashMap<>();
for (byte b:arr){
Integer count=map.get(b);
if(count==null){
map.put(b,1);
}else {
map.put(b,count+1);
}
}
for (Map.Entry<Byte,Integer> entry:map.entrySet()){
nodes.add(new HCNode(entry.getKey(), entry.getValue()));
}
return nodes;
}
//根据叶子节点创建Huffman树
public static HCNode createHuffmanTree(List<HCNode> nodes){
while (nodes.size()>1){
Collections.sort(nodes);
HCNode leftNode=nodes.get(0);
HCNode rightNode=nodes.get(1);
HCNode parentNode=new HCNode(null, leftNode.weight+rightNode.weight);
parentNode.left=leftNode;
parentNode.right=rightNode;
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parentNode);
}
return nodes.get(0);
}
//根据Huffman树得到Huffman编码表
public static Map<Byte,String> getCodes(HCNode root) {
if (root == null) {
return null;
} else {
StringBuilder sb = new StringBuilder();
getCodes(root.left,"0",sb);
getCodes(root.right,"1",sb);
return encodingTable;
}
}
public static void getCodes(HCNode node,String code,StringBuilder sb){
StringBuilder temp=new StringBuilder(sb);
temp.append(code);
if(node!=null){
if(node.data==null){
getCodes(node.left,"0",temp);
getCodes(node.right,"1",temp);
}else {
encodingTable.put(node.data,temp.toString());
}
}
}
//arr 要压缩的字节数据
//根据arr得到的Huffman编码表
//压缩数据
public static byte[] zip(byte[] arr,Map<Byte,String> encodingTable){
StringBuilder sb=new StringBuilder();
for (byte b:arr){
sb.append(encodingTable.get(b));
}
int len= (sb.length()+7)/8;
byte[] bytes=new byte[len];
int count=0;
for (int i=0;i<sb.length();i+=8){
String s;
if(i+8>sb.length()){
s= sb.substring(i);
last=s;
}else {
s=sb.substring(i,i+8);
}
bytes[count++]=(byte)Integer.parseInt(s,2);
}
return bytes;
}
//zipData 压缩后的数据
//用原Huffman编码表对zipData解码
public static byte[] decode(byte[] zipData,Map<Byte,String> encodingTable){
StringBuilder sb=new StringBuilder();
for (int i=0;i<zipData.length;i++){
if(i==zipData.length-1){
sb.append(last);
break;
}
sb.append(toBin(zipData[i]));
}
Map<String,Byte> decodeTable=new HashMap<>();
for (Map.Entry<Byte,String> entry:encodingTable.entrySet()){
decodeTable.put(entry.getValue(),entry.getKey());
}
List<Byte> list=new ArrayList<>();
for (int i=0;i<sb.length();){
int count=1;
Byte b;
while (true){
String s=sb.substring(i,count+i);
b=decodeTable.get(s);
if(b==null){
count++;
}else {
break;
}
}
i+=count;
list.add(b);
}
byte[] arr=new byte[list.size()];
for (int i=0;i<list.size();i++){
arr[i]=list.get(i);
}
return arr;
}
//转二进制
public static String toBin(byte b){
int temp=b;
temp |= 256;
String s=Integer.toBinaryString(temp);
return s.substring(s.length()-8);
}
算法:Huffman编码实现数据压缩以及解压
最新推荐文章于 2022-12-23 04:02:38 发布