日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用赫夫曼树进行文件解压

發(fā)布時間:2023/12/3 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用赫夫曼树进行文件解压 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

思路分析

代碼實現(xiàn)

package com.atguigu.huffmancode;import com.sun.org.glassfish.external.statistics.CountStatistic; import com.sun.org.glassfish.external.statistics.StringStatistic;import javax.xml.bind.SchemaOutputResolver; import java.io.*; import java.security.AlgorithmConstraints; import java.util.*;/*** @創(chuàng)建人 wdl* @創(chuàng)建時間 2021/3/27* @描述*/ public class HuffmanCode {public static void main(String[] args) {//測試壓縮文件 // String srcFile="C://Users//王東梁//Desktop//88888888.png"; // String dstFile="C://Users//王東梁//Desktop//dst.zip"; // zipFile(srcFile,dstFile); // System.out.println("壓縮文件成功");//測試解壓文件String zipFile="C://Users//王東梁//Desktop//dst.zip";String dstFile="C://Users//王東梁//Desktop//99999999.png";unZipFile(zipFile,dstFile);System.out.println("解壓文件成功");// String content="i like like like java do you like a java"; // byte[] contentBytes = content.getBytes(); // System.out.println(contentBytes.length);//40 // // byte[] huffmanCodesBytes = huffmanZip(contentBytes); // System.out.println("壓縮后的結(jié)果"+Arrays.toString(huffmanCodesBytes)+huffmanCodesBytes.length); // // //測試一把byteToBitString方法 // byte[] sourceBytes = decode(huffmanCodes, huffmanCodesBytes); // System.out.println(new String(sourceBytes));// // List<Node> nodes = getNodes(contentBytes); // System.out.println(nodes); // // //測試一把,創(chuàng)建的二叉樹 // System.out.println("赫夫曼樹"); // Node huffmanTreeRoot = createHuffmanTree(nodes); // System.out.println("前序遍歷"); // huffmanTreeRoot.preOrder(); // // //測試一把是否生成了對應(yīng)的赫夫曼編碼 // Map<Byte, String> huffmanCodes = getCodes(huffmanTreeRoot); // System.out.println("生成的赫夫曼編碼表"+huffmanCodes); // // //測試 // byte[] huffmanCodeBytes = zip(contentBytes, huffmanCodes); // System.out.println(Arrays.toString(huffmanCodeBytes));//17}//編寫一個方法,完成對壓縮文件的解壓/**** @param zipFile 要解壓的文件的位置* @param dstFile 將文件解壓到哪個路徑*/public static void unZipFile(String zipFile,String dstFile){//定義文件的輸入流InputStream is=null;//定義一個對象輸入流ObjectInputStream ois=null;//定義一個文件的輸出流OutputStream os=null;try {//創(chuàng)建文件輸入流is = new FileInputStream(zipFile);//創(chuàng)建一個和is關(guān)聯(lián)的對象輸入流ois = new ObjectInputStream(is);//讀取byte數(shù)組huffmanBytesbyte[] huffmanBytes = (byte[]) ois.readObject();//讀取赫夫曼編碼表Map<Byte,String> huffmanCodes = (Map<Byte, String>) ois.readObject();//解碼byte[] bytes = decode(huffmanCodes, huffmanBytes);//將bytes數(shù)組寫入到目標文件os = new FileOutputStream(dstFile);//寫數(shù)據(jù)到dstFile文件os.write(bytes);} catch (Exception e) {e.printStackTrace();} finally {try {is.close();os.close();ois.close();} catch (Exception e) {System.out.println(e.getMessage());}}}//編寫方法,將一個文件進行壓縮/**** @param srcFile 你傳入的希望壓縮的文件的全路徑* @param dstFile 我們壓縮后將壓縮文件放到哪個目錄*/public static void zipFile(String srcFile,String dstFile){//創(chuàng)建輸出流ObjectOutputStream oos=null;OutputStream os=null;FileInputStream is=null;try {//創(chuàng)建文件的輸入流is = new FileInputStream(srcFile);//創(chuàng)建一個和源文件大小一樣的byte[]byte[] b = new byte[is.available()];//讀取文件is.read(b);//直接對源文件進行壓縮byte[] huffmanBytes = huffmanZip(b);//創(chuàng)建文件的輸出流,存放壓縮文件os = new FileOutputStream(dstFile);//創(chuàng)建一個和文件輸入流關(guān)聯(lián)的ObjectOutputStreamoos = new ObjectOutputStream(os);//我們赫夫曼編碼后的字節(jié)數(shù)組寫入壓縮文件oos.writeObject(huffmanBytes);//這里我們以對象流的方式寫入赫夫曼編碼,是為了以后我們回復(fù)源文件時使用//注意一定要包赫夫曼編碼寫入壓縮文件oos.writeObject(huffmanCodes);} catch (Exception e) {System.out.println(e.getMessage());} finally {try {is.close();oos.close();os.close();} catch (Exception e) {System.out.println(e.getMessage());}}}//完成數(shù)據(jù)的解壓//思路//1.將huffmanCodeBytes//重現(xiàn)先轉(zhuǎn)成赫夫曼編碼對應(yīng)的二進制的字符串“0100000//2.、將“111"對照赫夫曼編碼=》i like/**** @param huffmanCodes 哈夫曼編碼表map* @param huffmanBytes 赫夫曼編碼的到的字節(jié)數(shù)組* @return 原來的字符串對應(yīng)的數(shù)組*///編寫一個方法,完成對壓縮數(shù)據(jù)的解碼private static byte[] decode(Map<Byte,String> huffmanCodes,byte[] huffmanBytes){//1.先得到huffmanBytes 對應(yīng)的二進制字符串StringBuilder stringBuilder = new StringBuilder();//將byte數(shù)組轉(zhuǎn)成二進制的字符串編碼for (int i = 0; i < huffmanBytes.length; i++) {byte b = huffmanBytes[i];//判斷是不是最后一個字節(jié)boolean flag=(i==huffmanBytes.length-1);stringBuilder.append( byteToBitString(!flag,b));}//吧字符串按照指定的赫夫曼編碼進行解碼//把赫夫曼編碼表進行調(diào)換,因為要反向查詢Map<String, Byte> map = new HashMap<>();for(Map.Entry<Byte, String> entry:huffmanCodes.entrySet()){map.put(entry.getValue(),entry.getKey());} // System.out.println(map);//創(chuàng)建一個集合,存放byteArrayList<Byte> list = new ArrayList<>();for (int i = 0; i < stringBuilder.length();) {//i可以理解成就是一個索引,掃描stringBuilderint count=1;//小的計數(shù)器boolean flag=true;Byte b=null;while (flag){//遞增的取出key 1//取出一個字符'1' '0'String key = stringBuilder.substring(i, i + count);//i不動,讓count移動,直到匹配到一個字符b=map.get(key);if(b==null){//說明沒有匹配到count++;}else {//匹配到flag=false;}}list.add(b);i+=count;//i直接移動到count}//for循環(huán)結(jié)束后,我們list中就存放了所有的字符"i like"//吧list中的數(shù)據(jù)放入到byte數(shù)組并返回byte[] b = new byte[list.size()];for (int i = 0; i < b.length; i++) {b[i]=list.get(i);}return b;}/*** 將一個byte轉(zhuǎn)成一個二進制的字符串* @param b* @param flag 表示是否需要補高位,如果是true,表示需要補高位,如果是false表示不補,如果是最后一個字節(jié),無需補高位* @return 是該b 對應(yīng)的二進制的字符串,(注意是按補碼返回)*/private static String byteToBitString(boolean flag,byte b){//使用變量保存bint temp=b;//b轉(zhuǎn)成int//如果是正數(shù)我們還存在補高位的問題if(flag){temp|=256;}String str = Integer.toBinaryString(temp);//返回的是temp對應(yīng)的二進制補碼if(flag){return str.substring(str.length()-8);}else {return str;}}//使用一個方法,將前面的方法封裝起來,便于我們的調(diào)用/**** @param bytes 原始的字符串對應(yīng)的字節(jié)數(shù)組* @return 是經(jīng)過赫夫曼編碼處理后的子節(jié)數(shù)組(壓縮后的數(shù)組)*/private static byte[] huffmanZip(byte[] bytes){List<Node> nodes = getNodes(bytes);//根據(jù)nodes創(chuàng)建赫夫曼樹Node huffmanTreeRoot = createHuffmanTree(nodes);//生成了對應(yīng)的赫夫曼編碼Map<Byte, String> huffmanCodes = getCodes(huffmanTreeRoot);//根據(jù)生成的赫夫曼編碼,壓縮的到壓縮后的赫夫曼編碼字節(jié)數(shù)組byte[] huffmanCodeBytes = zip(bytes, huffmanCodes);return huffmanCodeBytes;}/**** @param bytes 這時原始的字符串對應(yīng)的byte[]* @param huffmanCodes 生成的赫夫曼編碼map* @return 返回赫夫曼編碼表處理后的byte[]*///編寫一個方法,將字符串對應(yīng)的byte[]數(shù)組,通過生成的赫夫曼編碼表,返回一個赫夫曼編碼壓縮有的byte[]private static byte[] zip(byte[] bytes,Map<Byte,String> huffmanCodes){//1.先利用huffmanCodes將bytes轉(zhuǎn)成赫夫曼編碼對應(yīng)的字符串StringBuilder stringBuilder = new StringBuilder();//遍歷bytes數(shù)組for(byte b:bytes){stringBuilder.append(huffmanCodes.get(b));}System.out.println("測試stringBuilder="+stringBuilder.toString());//將1010111011 轉(zhuǎn)成byte數(shù)組//統(tǒng)計返回byte[] huffmanCodeBytes 長度//一句話 int len=(stringBuilder.length()+7)/8int len;if(stringBuilder.length()%8==0){len=stringBuilder.length()/8;}else {len=stringBuilder.length()/8+1;}//創(chuàng)建存儲壓縮有的byte[]byte[] huffmanCodeBytes=new byte[len];int index=0;//記錄是第幾個bytefor (int i = 0; i < stringBuilder.length(); i+=8) {//因為每8位對應(yīng)一個byte,所以步長+8String strByte;if(i+8>stringBuilder.length()){//不夠8位strByte = stringBuilder.substring(i);}else {strByte = stringBuilder.substring(i, i + 8);}//將strByte轉(zhuǎn)成一個byte,放入到huffmanCodeByteshuffmanCodeBytes[index]= (byte) Integer.parseInt(strByte,2);index++;}return huffmanCodeBytes;}//生成赫夫曼樹對應(yīng)的赫夫曼編碼//思路://1.將赫夫曼編碼表存放在Map<Byte,String>形式static Map<Byte,String> huffmanCodes= new HashMap<Byte,String>();// 32->01 97->100...//2.在生成赫夫曼編碼表示,需要去拼接璐姐,定義一個StringBuilder存儲某個葉子結(jié)點的路徑static StringBuilder stringBuilder=new StringBuilder();//這里為了調(diào)用方便,我們重載getCodesprivate static Map<Byte,String> getCodes(Node root){if(root==null){return null;}//處理root的左子樹getCodes(root.left,"0",stringBuilder);//處理root的右子樹getCodes(root.right,"1",stringBuilder);return huffmanCodes;}/*** 功能:將傳入的node節(jié)點的所有葉子節(jié)點的赫夫曼編碼的到,并放入到huffmanCodes集合* @param node 傳入節(jié)點* @param code 路徑:左子節(jié)點是0,右子節(jié)點是1* @param stringBuilder 是用于拼接路徑*/private static void getCodes(Node node,String code,StringBuilder stringBuilder){StringBuilder stringBuilder2 = new StringBuilder(stringBuilder);//將code加入到stringBuild2stringBuilder2.append(code);if(node!=null){//如果node==null不處理//判斷當前node是葉子結(jié)點還是非葉子節(jié)點if(node.data==null){//非葉子節(jié)點//遞歸處理//向左getCodes(node.left,"0",stringBuilder2);//向右getCodes(node.right,"1",stringBuilder2);}else {//說明是一個葉子結(jié)點//表示找到了某個葉子節(jié)點的最后huffmanCodes.put(node.data,stringBuilder2.toString());}}}//前序遍歷的方法private static void preOrder(Node root){if(root!=null){root.preOrder();}else {System.out.println("赫夫曼樹為空");}}/**** @param bytes 接收字節(jié)數(shù)組* @return 返回的就是List形式*/private static List<Node> getNodes(byte[] bytes){//1.創(chuàng)建一個ArrayListArrayList<Node> nodes = new ArrayList<>();//遍歷bytes 統(tǒng)計每一個byte出現(xiàn)的次數(shù)->map[key,value]HashMap<Byte, Integer> counts = new HashMap<>();for(byte b:bytes){Integer count=counts.get(b);if (count==null){//map中還沒有這個字符數(shù)據(jù),第一次counts.put(b,1);}else {counts.put(b,count+1);}}//把每一個鍵值對轉(zhuǎn)成Node對象,并加入到nodes集合//遍歷mapfor(Map.Entry<Byte,Integer> entry:counts.entrySet()){nodes.add(new Node(entry.getKey(),entry.getValue()));}return nodes;}//可以通過List創(chuàng)建對應(yīng)的赫夫曼樹private static Node createHuffmanTree(List<Node> nodes){while (nodes.size()>1){//排序,從小到大Collections.sort(nodes);//取出第一顆最小的二叉樹Node leftNode = nodes.get(0);//取出第二顆最小的二叉樹Node rightNode = nodes.get(1);//創(chuàng)建一顆新的二叉樹,它的根節(jié)點沒有data,只有權(quán)值Node parent=new Node(null,leftNode.weight+rightNode.weight);parent.left=leftNode;parent.right=rightNode;//將已經(jīng)處理的兩顆二叉樹從nodes刪除nodes.remove(leftNode);nodes.remove(rightNode);//將新的二叉樹,加入到nodesnodes.add(parent);}//nodes最后的節(jié)點,就是哈夫曼樹的根節(jié)點return nodes.get(0);}}//創(chuàng)建Node,待數(shù)據(jù)和權(quán)值 class Node implements Comparable<Node>{Byte data;//存放數(shù)據(jù)(字符)本身,比如'a'=>97 ' '=>32int weight;//權(quán)值,表示字符出現(xiàn)的次數(shù)Node left;Node right;public Node(Byte data, int weight) {this.data = data;this.weight = weight;}@Overridepublic int compareTo(Node o) {//從小到大排序return this.weight-o.weight;}@Overridepublic 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();}}}

總結(jié)

以上是生活随笔為你收集整理的用赫夫曼树进行文件解压的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久综合五月婷婷 | 小柔的淫辱日记(h | 国产欧美高清 | 天天干天天摸 | 亚洲在线一区二区三区 | 美女被叉叉的影院 | 风间由美在线视频 | 91桃色视频在线观看 | 69久久久久久 | 中文在线a∨在线 | 动漫3d精品一区二区三区乱码 | 68日本xxxxxⅹxxx59| 无码人妻精品一区二区蜜桃色欲 | 久久精品久久精品 | 超碰国产人人 | 黄色天堂网站 | 三上悠亚 电影 | 少妇一级淫免费放 | 免费成人深夜小野草 | 青娱网电信一区电信二区电信三区 | 先锋av资源在线 | 91视频观看 | 久久9999久久免费精品国产 | 熟妇五十路六十路息与子 | 国产精品麻豆果冻传媒在线播放 | 亚洲欧美激情另类校园 | 风韵少妇spa私密视频 | 国产伦精品一区二区三区高清版禁 | 男生插女生的网站 | 99色国产| 色婷婷aⅴ | 红猫大本营在线观看的 | 欧美日韩高清一区二区 国产亚洲免费看 | 福利在线免费 | 小黄网站在线观看 | 国产初高中真实精品视频 | www.一区二区 | 艳母免费在线观看 | 国产精品国产三级国产专播精品人 | 中文无码一区二区三区在线观看 | 国产99久久久欧美黑人 | 人人澡超碰碰 | 色版视频在线观看 | jzzijzzij亚洲成熟少妇在线观看 久久久精品人妻一区二区三区 | 国产蜜臀av一区二区 | 亚洲国产免费 | 人人插插| 国产美女免费观看 | 99这里有精品视频 | 波多野结衣理论片 | 椎名由奈av一区二区三区 | 日韩欧美一 | 成人激情文学 | 亚洲天堂伊人网 | 激情综合av | 青青视频免费在线观看 | 久久性生活片 | 欧美在线免费观看 | 国产精品9999 | 亚洲男人的天堂av | 超碰人人网 | 成人性生交大片免费看中文 | 肥熟女一区二区三肥熟女 | 亚洲精品国产免费 | www.超碰在线观看 | 日批在线视频 | 影音先锋啪啪 | 日韩色综合网 | 国语对白一区二区三区 | 国产毛片91 | 日本精品久久久久久 | 欧美日韩一区电影 | 久久噜噜色综合一区二区 | 18禁男女爽爽爽午夜网站免费 | 在线能看的av | 国产精品久久久免费 | 大桥未久恸哭の女教师 | 岛国av网站 | 久久精品免费网站 | 国产片一区二区 | av巨作 | a免费毛片 | 中国黄色免费 | 顶级毛茸茸aaahd极品 | 国模私拍大尺度裸体av | 欧美精品二区 | 全黄一级裸体片 | 亚洲国产成人91精品 | 欧美一级在线视频 | 久艹在线| 色激情网 | 一区二区三区四区高清视频 | 卡通动漫精品一区二区三区 | 中文无码熟妇人妻av在线 | 一级黄av| 99热| 国产极品一区 | 一区二区传媒有限公司 | 曰韩精品 |