标签:
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 }
标签:
原文地址:http://www.cnblogs.com/upside-down/p/5882648.html