java實現哈夫曼文件解壓縮
本文實例為大傢分享瞭java實現哈夫曼文件解壓縮的具體代碼,供大傢參考,具體內容如下
1、哈夫曼壓縮對已經經過壓縮處理的文件壓縮率比較低,比如ppt和視頻。
2、這個程序主要涉及到集合、樹、IO相關知識。
字符的統計可以用map集合進行統計。
哈夫曼樹的構建過程也並不復雜:
①先對樹的集合按照根節點大小進行排序
②拿出根節點數值最小的兩棵樹,用它兩構建成一顆新的樹;
③從集合中刪除之前那兩顆根節點最小的數;
④把新生成的樹加入到集合中
一直循環重復上面的過程,直到集合的大小變成1為止;
寫出、讀取文件時註意使用對象流Object流。
3、個程序可以對字符進行壓縮,也可以對文件進行壓縮。代碼中的主函數中隻是調用瞭對文件解壓縮的方法,若想對字符進行解壓縮,可以調用對應的方法。
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");//對剛才的文件進行解壓,解壓後的文件名稱叫做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)//非葉子結點 { //向左遞歸 getCodes(node.leftNode,"0",stringBuilder2); //向右遞歸 getCodes(node.rightNode,"1",stringBuilder2); } else //如果是葉子結點 { 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);//通過鍵獲取值 if(count==null)//說明此時map集合中還沒有改字符 { 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);//先對集合進行排序 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;//字符出現的次數 Node leftNode; Node rightNode; public Node(Byte data,int weight)//構造器 { 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(); } } }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Java數據結構之哈夫曼樹概述及實現
- java數據結構圖論霍夫曼樹及其編碼示例詳解
- Java進階核心之InputStream流深入講解
- Java中IO流解析及代碼實例
- Java Socket上的Read操作阻塞問題詳解