码迷,mamicode.com
首页 > 其他好文 > 详细

HuffmanCode

时间:2016-09-18 19:26:15      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

  1 package huffman;
  2 
  3 import java.io.BufferedInputStream;
  4 import java.io.BufferedOutputStream;
  5 import java.io.File;
  6 import java.io.FileInputStream;
  7 import java.io.FileOutputStream;
  8 import java.io.IOException;
  9 import java.io.ObjectInputStream;
 10 import java.io.ObjectOutputStream;
 11 import java.io.RandomAccessFile;
 12 import java.util.ArrayList;
 13 import java.util.Collections;
 14 import java.util.Comparator;
 15 import java.util.HashMap;
 16 import java.util.List;
 17 import java.util.Map;
 18 import java.util.Set;
 19 
 20 public class HuffmanCode {
 21 
 22     private static class Tree {
 23 
 24         private class Node {
 25             char ch;
 26             int weight;
 27             Node left, right;
 28             String code = "";
 29 
 30             public Node() {
 31             }
 32 
 33             public Node(char ch, int weight) {
 34                 this.ch = ch;
 35                 this.weight = weight;
 36             }
 37         }
 38 
 39         Node root;
 40 
 41         public Tree(char ch, int weight) {
 42             root = new Node(ch, weight);
 43         }
 44 
 45         public Tree(Tree t1, Tree t2) {
 46             root = new Node();
 47             root.left = t1.root;
 48             root.right = t2.root;
 49             root.weight = t1.root.weight + t2.root.weight;
 50         }
 51 
 52     }
 53 
 54     public static int[] getCharacterFrequency(String text) {
 55         int[] counts = new int[256];
 56 
 57         for (int i = 0; i < text.length(); i++)
 58             counts[(int) text.charAt(i)]++;
 59 
 60         return counts;
 61     }
 62 
 63     private static class MyComparator implements Comparator<Tree> {
 64 
 65         @Override
 66         public int compare(Tree o1, Tree o2) {
 67             if (o1.root.weight < o2.root.weight)
 68                 return -1;
 69             else if (o1.root.weight > o2.root.weight)
 70                 return 1;
 71             else
 72                 return 0;
 73         }
 74 
 75     }
 76 
 77     public static Tree getHuffmanTree(int[] counts) {
 78         List<Tree> list = new ArrayList<>();
 79         for (int i = 0; i < counts.length; i++)
 80             if (counts[i] > 0)
 81                 list.add(new Tree((char) i, counts[i]));
 82         while (list.size() > 1) {
 83             Collections.sort(list, new MyComparator());
 84             list.add(new Tree(list.remove(0), list.remove(0)));
 85         }
 86         return list.remove(0);
 87     }
 88 
 89     private static void assignCode(Tree.Node root, String[] codes) {
 90         if (root.left == null)
 91             codes[(int) root.ch] = "0";
 92         else
 93             assignCodes(root, codes);
 94     }
 95 
 96     private static void assignCodes(huffman.HuffmanCode.Tree.Node root, String[] codes) {
 97         if (root.left != null) {
 98             root.left.code = root.code + "0";
 99             assignCodes(root.left, codes);
100 
101             root.right.code = root.code + "1";
102             assignCodes(root.right, codes);
103         } else
104             codes[(int) root.ch] = root.code;
105     }
106 
107     public static String[] getCode(Tree.Node root) {
108         if (root == null)
109             return null;
110         String[] codes = new String[256];
111         assignCode(root, codes);
112 
113         return codes;
114     }
115 
116     private static int[] getCounts(String filename) throws Exception {
117         BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(filename)));
118 
119         int[] counts = new int[256];
120         int r;
121         while ((r = in.read()) != -1)
122             counts[r]++;
123         in.close();
124 
125         return counts;
126     }
127 
128     public static String textToBits(String text) {
129         int[] counts = getCharacterFrequency(text);
130         Tree tree = getHuffmanTree(counts);
131         String[] codes = getCode(tree.root);
132 
133         StringBuilder sb = new StringBuilder();
134         for (int i = 0; i < text.length(); i++) {
135             int textByte = (int) text.charAt(i);
136             sb.append(codes[textByte]);
137         }
138 
139         return sb.toString();
140     }
141 
142     public static String[] compressFile(String filename) {
143         try {
144             int[] counts = getCounts(filename);
145             Tree tree = getHuffmanTree(counts);
146             String[] codes = getCode(tree.root);
147             storeCodes(filename, codes);
148             encode(filename, codes);
149         } catch (Exception e) {
150             e.printStackTrace();
151             return null;
152         }
153         return new String[] { filename + ".new", filename + ".huf" };
154     }
155 
156     private static void encode(String filename, String[] codes) throws Exception {
157         BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(filename)));
158         BitOutputStream out = new BitOutputStream(new File(filename + ".new"));
159 
160         int r;
161         while ((r = in.read()) != -1)
162             out.writeBit(codes[r]);
163 
164         in.close();
165         out.close();
166     }
167 
168     private static void storeCodes(String filename, String[] codes) throws Exception {
169         ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(filename + ".huf"));
170         objOut.writeObject(codes);
171         objOut.close();
172     }
173 
174     public static String expandFile(String compressedFile, String codesFile) {
175         String filename = compressedFile.substring(0, compressedFile.indexOf(‘.‘)) + "(2).txt";
176         try (ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(codesFile));
177                 BufferedInputStream in = new BufferedInputStream(new FileInputStream(compressedFile));
178                 BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(filename));) {
179             String[] codes = (String[]) objIn.readObject();
180             Map<String, Integer> map = new HashMap<>();
181             for (int i = 0; i < codes.length; i++)
182                 if (codes[i] != null)
183                     map.put(codes[i], i);
184             Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
185 
186             boolean has;
187             StringBuilder sb = new StringBuilder();
188             int n=in.read();
189             if(n==8)
190                 n=0;
191             int last=-1;
192             while (in.available()>0) {
193                 if(last!=-1){
194                     String bit8 = "0000000" + Integer.toBinaryString(last);
195                     sb.append(bit8.substring(bit8.length() - 8));
196                     has = true;
197                     while (sb.length() > 0 && has) {
198                         has = false;
199                         for (Map.Entry<String, Integer> entry : entrySet) {
200                             String code = entry.getKey();
201                             if (sb.indexOf(code) == 0) {
202                                 out.write(entry.getValue());
203                                 sb.delete(0, code.length());
204                                 has = true;
205                                 break;
206                             }
207                         }
208                     }
209                 }
210                 last=in.read();
211             }
212             
213             String bit8 = "0000000" + Integer.toBinaryString(last);
214             sb.append(bit8.substring(bit8.length() - 8));
215             sb.delete(sb.length()-n, sb.length());
216             has=true;
217             while (sb.length() > 0 && has) {
218                 has = false;
219                 for (Map.Entry<String, Integer> entry : entrySet) {
220                     String code = entry.getKey();
221                     if (sb.indexOf(code) == 0) {
222                         out.write(entry.getValue());
223                         sb.delete(0, code.length());
224                         has = true;
225                         break;
226                     }
227                 }
228             }
229         } catch (Exception e) {
230             e.printStackTrace();
231             return null;
232         }
233         return filename;
234     }
235 
236     private static class BitOutputStream {
237         private RandomAccessFile raf;
238         private int count = 0;
239         private int value = 0;
240         private static final int mask = 1;
241 
242         private BitOutputStream(File file) throws Exception {
243             raf=new RandomAccessFile(file, "rw");
244             raf.setLength(0);
245             raf.write(1);
246         }
247 
248         private void writeBit(char bit) throws IOException {
249             count++;
250             value <<= 1;
251 
252             if (‘1‘ == bit)
253                 value |= mask;
254 
255             if (count == 8) {
256                 raf.write(value);
257                 count = 0;
258                 value = 0;
259             }
260         }
261 
262         private void writeBit(String code) throws IOException {
263             for (int i = 0; i < code.length(); i++)
264                 writeBit(code.charAt(i));
265         }
266 
267         private void close() throws IOException {
268             if (count > 0) {
269                 value <<= (8 - count);
270                 raf.write(value);
271             }
272 
273             raf.seek(0);
274             raf.write(8-count);
275             raf.close();
276         }
277 
278     }
279 
280 }

 

HuffmanCode

标签:

原文地址:http://www.cnblogs.com/upside-down/p/5882648.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!