欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java實(shí)現(xiàn)哈夫曼文件解壓縮

 更新時(shí)間:2021年06月16日 15:40:05   作者:YSoup  
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)哈夫曼文件解壓縮,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了java實(shí)現(xiàn)哈夫曼文件解壓縮的具體代碼,供大家參考,具體內(nèi)容如下

1、哈夫曼壓縮對(duì)已經(jīng)經(jīng)過(guò)壓縮處理的文件壓縮率比較低,比如ppt和視頻。

2、這個(gè)程序主要涉及到集合、樹(shù)、IO相關(guān)知識(shí)。

字符的統(tǒng)計(jì)可以用map集合進(jìn)行統(tǒng)計(jì)。
哈夫曼樹(shù)的構(gòu)建過(guò)程也并不復(fù)雜:
①先對(duì)樹(shù)的集合按照根節(jié)點(diǎn)大小進(jìn)行排序
②拿出根節(jié)點(diǎn)數(shù)值最小的兩棵樹(shù),用它兩構(gòu)建成一顆新的樹(shù);
③從集合中刪除之前那兩顆根節(jié)點(diǎn)最小的數(shù);
④把新生成的樹(shù)加入到集合中
一直循環(huán)重復(fù)上面的過(guò)程,直到集合的大小變成1為止;
寫(xiě)出、讀取文件時(shí)注意使用對(duì)象流Object流。

3、個(gè)程序可以對(duì)字符進(jìn)行壓縮,也可以對(duì)文件進(jìn)行壓縮。代碼中的主函數(shù)中只是調(diào)用了對(duì)文件解壓縮的方法,若想對(duì)字符進(jìn)行解壓縮,可以調(diào)用對(duì)應(yīng)的方法。

4、代碼如下:

package huffmancode;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HuffManCode 
{

 public static void main(String[] args) 
 {
  String srcFile="d://mydata.txt";//要壓縮的文件
  String dstFile="d://mydata.zip";//壓縮后的文件
  zipFile(srcFile, dstFile);//壓縮文件
  System.out.println("壓縮成功!");
  
  unZipFile(dstFile,"d://unzip.txt");//對(duì)剛才的文件進(jìn)行解壓,解壓后的文件名稱叫做unzip.txt
  System.out.println("解壓文件成功!");  
 }
 
 public static void unZipFile(String zipFile,String dstFile)
 {
  InputStream inputStream=null;
  ObjectInputStream objectInputStream=null;
  OutputStream outputStream=null;
  try 
  {
   inputStream=new FileInputStream(zipFile);
   objectInputStream=new ObjectInputStream(inputStream);
   byte [] array= (byte [])objectInputStream.readObject();
   Map<Byte,String> map=(Map<Byte,String>)objectInputStream.readObject();
   byte[] decode = decode(map, array);
   outputStream=new FileOutputStream(dstFile);
   outputStream.write(decode);
  } catch (Exception e) 
  {
   System.out.println(e);
  }finally
  {
   try {
    outputStream.close();
    objectInputStream.close();
    inputStream.close();
    
   } catch (Exception e2) {
    System.out.println(e2);
   }
   
  }
  
  
 }
 
 public static void zipFile(String srcFile,String dstFile)
 {
  FileInputStream inputStream=null;
  OutputStream outputStream=null;
  ObjectOutputStream objectOutputStream=null;
  
  try 
  {
   inputStream=new FileInputStream(srcFile);
   byte [] b=new byte[inputStream.available()];
   inputStream.read(b);
   byte[] huffmanZip = huffmanZip(b);
   outputStream=new FileOutputStream(dstFile);
   objectOutputStream=new ObjectOutputStream(outputStream);
   objectOutputStream.writeObject(huffmanZip);
   objectOutputStream.writeObject(map);
  } catch (Exception e)
  {
   System.out.println(e);
  }
  finally 
  {
   if(inputStream!=null)
   {
    try 
    {
     objectOutputStream.close();
     outputStream.close();
     inputStream.close();//釋放資源
    
    } catch (Exception e2) 
    {
     System.out.println(e2);
    }
    
   }  
  }
 }
 
 private static byte[] decode(Map<Byte, String> map,byte [] array)
 {
  StringBuilder stringBuilder = new StringBuilder();
  for(int i=0;i<array.length;i++)
  {
   boolean flag=(i==array.length-1);
   stringBuilder.append(byteToBitString(!flag, array[i]));
  }
  
  Map<String, Byte> map2=new HashMap<String, Byte>();//反向編碼表
  Set<Byte> keySet = map.keySet();
  for(Byte b:keySet)
  {
   String value=map.get(b);
   map2.put(value, b);
  }
  List<Byte> list=new ArrayList<Byte>();
  for (int i = 0; i < stringBuilder.length();) 
  {
   int count=1;
   boolean flag=true;
   Byte byte1=null;
   while (flag) 
   {
    String substring = stringBuilder.substring(i, i+count);
    byte1 = map2.get(substring);
    if(byte1==null)
    {
     count++;
    }
    else 
    {
     flag=false;
    }
    
   }
   list.add(byte1);
   i+=count;  
  }
  
  byte [] by=new byte[list.size()];
  for(int i=0;i<by.length;i++)
  {
   by[i]=list.get(i);
  }
  return by;
 }
 
 private static String byteToBitString(boolean flag, byte b)
 {
  int temp=b;
  if(flag)
  {
   temp|=256;
  }
  
  String binaryString = Integer.toBinaryString(temp);
  if(flag)
  {
   return binaryString.substring(binaryString.length()-8);
  }
  else
  {
   return binaryString;
  }
  
 }
 
 private static byte[] huffmanZip(byte [] array)
 {
  List<Node> nodes = getNodes(array);
  Node createHuffManTree = createHuffManTree(nodes);
  Map<Byte, String> m=getCodes(createHuffManTree);
  byte[] zip = zip(array, m);
  return zip; 
 }
 
 //
 private static byte[] zip(byte [] array,Map<Byte,String> map)
 {
  StringBuilder sBuilder=new StringBuilder();
  for(byte item:array)
  {
   String value=map.get(item);
   sBuilder.append(value);
  }
  //System.out.println(sBuilder);
  int len;
  if(sBuilder.toString().length()%8==0)//如果可以整除
  {
   len=sBuilder.toString().length()/8;
  }
  else //如果不能整除
  {
   len=sBuilder.toString().length()/8+1;
  }
  
  byte [] by=new byte[len];
  int index=0;
  for(int i=0;i<sBuilder.length();i+=8)
  {
   String string;
   if((i+8)>sBuilder.length())
   {
    string=sBuilder.substring(i);
   }
   else 
   {
    string=sBuilder.substring(i, i+8);
   }
      
   by[index]=(byte)Integer.parseInt(string,2);
   index++;
  }
  
  return by;
   
 }
 
 
 //重載
 private static Map<Byte, String> getCodes(Node root)
 {
  if(root==null)
  {
   return null;
  }
  getCodes(root.leftNode,"0",sBuilder);
  getCodes(root.rightNode,"1",sBuilder);
  return map;
 }
 
 
 
 //獲取哈夫曼編碼
  static Map<Byte, String> map=new HashMap<>();
  static StringBuilder sBuilder=new StringBuilder();
  public static void getCodes(Node node,String code,StringBuilder stringBuilder)
  {
   StringBuilder stringBuilder2=new StringBuilder(stringBuilder);
   stringBuilder2.append(code);
   if(node!=null)
   {
    if(node.data==null)//非葉子結(jié)點(diǎn)
    {
     //向左遞歸
     getCodes(node.leftNode,"0",stringBuilder2);
     //向右遞歸
     getCodes(node.rightNode,"1",stringBuilder2);
    }
    else //如果是葉子結(jié)點(diǎn)
    {
     map.put(node.data,stringBuilder2.toString());
    }
   }
  }
 
 
 
 public static List<Node> getNodes(byte [] array)
 {
  List<Node> list=new ArrayList<Node>();
  Map<Byte, Integer> map=new HashMap<Byte, Integer>();
  for(Byte data:array)
  {
   Integer count=map.get(data);//通過(guò)鍵獲取值
   if(count==null)//說(shuō)明此時(shí)map集合中還沒(méi)有改字符
   {
    map.put(data, 1);
   }
   else 
   {
    map.put(data,count+1);
   }
  }
  //遍歷map集合
  Set<Byte> set=map.keySet();
  for(Byte key:set)
  {
   int value=map.get(key);
   Node node=new Node(key, value);
   list.add(node);
  }
  return list;
 }
 
 private static Node createHuffManTree(List<Node> list)
 {
  while(list.size()>1)
  {
   Collections.sort(list);//先對(duì)集合進(jìn)行排序
   Node leftNode=list.get(0);
   Node rightNode=list.get(1);
   
   Node parentNode=new Node(null, leftNode.weight+rightNode.weight);
   parentNode.leftNode=leftNode;
   parentNode.rightNode=rightNode;
   
   list.remove(leftNode);
   list.remove(rightNode);
   
   list.add(parentNode);
  }
  return list.get(0);
  
 }

}

class Node implements Comparable<Node>
{
 Byte data;//字符
 int weight;//字符出現(xiàn)的次數(shù)
 Node leftNode;
 Node rightNode;
 
 public Node(Byte data,int weight)//構(gòu)造器
 {
  this.data=data;
  this.weight=weight;
 }

 @Override
 public int compareTo(Node o) 
 {
  return this.weight-o.weight;
 }

 @Override
 public String toString() 
 {
  return "Node [data=" + data + ", weight=" + weight + "]";
 }
 
 //前序遍歷
 public void preOrder()
 {
  System.out.println(this);
  if(this.leftNode!=null)
  {
   this.leftNode.preOrder();
  }
  if(this.rightNode!=null)
  {
   this.rightNode.preOrder();
  }
 }
 
 
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring框架十一種常見(jiàn)異常的解決方法匯總

    Spring框架十一種常見(jiàn)異常的解決方法匯總

    今天小編就為大家分享一篇關(guān)于Spring框架十一種常見(jiàn)異常的解決方法匯總,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • Java8?Optional常用方法使用場(chǎng)景分析

    Java8?Optional常用方法使用場(chǎng)景分析

    這篇文章主要介紹了Java8?Optional常用方法使用場(chǎng)景,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • grails不能運(yùn)行fork模式解決方法

    grails不能運(yùn)行fork模式解決方法

    這篇文章主要介紹了如何解決grails2.3.2中不能運(yùn)行fork模式的異常,大家參考使用吧
    2013-11-11
  • Java socket 如何獲取gps定位

    Java socket 如何獲取gps定位

    在Java中使用Socket來(lái)直接獲取GPS定位信息并不直接可行,因?yàn)镚PS數(shù)據(jù)通常不是通過(guò)Socket通信來(lái)獲取的,本文給大家介紹Java socket 獲取gps定位的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • MyBatis?如何使項(xiàng)目兼容多種數(shù)據(jù)庫(kù)的解決方案

    MyBatis?如何使項(xiàng)目兼容多種數(shù)據(jù)庫(kù)的解決方案

    要想做兼容多種數(shù)據(jù)庫(kù),那毫無(wú)疑問(wèn),我們首先得明確我們要兼容哪些數(shù)據(jù)庫(kù),他們的數(shù)據(jù)庫(kù)產(chǎn)品名稱是什么,本次我們講解了一套使項(xiàng)目兼容多種數(shù)據(jù)庫(kù)的方案,對(duì)MyBatis項(xiàng)目兼容多種數(shù)據(jù)庫(kù)操作方法感興趣的朋友一起看看吧
    2024-05-05
  • Spring Shell應(yīng)用程序開(kāi)發(fā)流程解析

    Spring Shell應(yīng)用程序開(kāi)發(fā)流程解析

    這篇文章主要介紹了Spring Shell應(yīng)用程序開(kāi)發(fā)流程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Java web含驗(yàn)證碼及權(quán)限登錄實(shí)例代碼

    Java web含驗(yàn)證碼及權(quán)限登錄實(shí)例代碼

    這篇文章主要介紹了Java web含驗(yàn)證碼及權(quán)限登錄實(shí)例代碼,所用到的開(kāi)發(fā)工具為myeclipse10,MySQL數(shù)據(jù)庫(kù),具體實(shí)現(xiàn)代碼大家參考下本文吧
    2017-03-03
  • 在springboot中如何給mybatis加攔截器

    在springboot中如何給mybatis加攔截器

    這篇文章主要介紹了在springboot中如何給mybatis加攔截器,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • JAVA中的隊(duì)列(Queue)詳解

    JAVA中的隊(duì)列(Queue)詳解

    這篇文章主要介紹了JAVA中的隊(duì)列(Queue)詳解,隊(duì)列是一種特殊的線性表,遵循先入先出、后入后出的基本原則,一般來(lái)說(shuō),它只允許在表的前端進(jìn)行刪除操作,需要的朋友可以參考下
    2023-07-07
  • Java SpringBoot容器注入對(duì)象詳解

    Java SpringBoot容器注入對(duì)象詳解

    本文通過(guò)實(shí)例代碼給大家詳解了springboot獲取ioc容器中注入的bean問(wèn)題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-09-09

最新評(píng)論