我一直在研究霍夫曼压缩和解压缩程序。在这个阶段,我的压缩程序可以正常工作,但是我似乎无法使解压缩代码重现已被压缩的原始文件。我想我做错了。完整的代码如下。请任何帮助将不胜感激。
import java.io.*;
import java.util.*;
public class HuffMain {
public static PriorityQueue<Node> q;
public static HashMap<Character, String> charToCode;
public static HashMap<String, Character> codeToChar;
@SuppressWarnings("resource")
public static void main(String[] args) throws FileNotFoundException {
// Read all the contents of the file
String text = new Scanner(new File("text.txt")).useDelimiter("\\A").next();
// Count the frequency of all the characters
HashMap<Character, Integer> dict = new HashMap<Character, Integer>();
for(int i = 0; i < text.length(); i++) {
char a = text.charAt(i);
if(dict.containsKey(a))
dict.put(a, dict.get(a)+1);
else
dict.put(a, 1);
}
// Create a forest (group of trees) by adding all the nodes to a priority queue
q = new PriorityQueue<Node>(100, new FrequencyComparator());
int n = 0;
for(Character c : dict.keySet()) {
q.add(new Node(c, dict.get(c)));
n++;
}
Node root = huffmain(n);
buildTable(root);
String compressed = compress(text);
saveToFile(compressed);
String decompressed = decompress(compressed);
writeToFile(decompressed);
}
// This method builds the tree based on the frequency of every characters
public static Node huffmain(int n) {
Node x, y;
for(int i = 1; i <= n-1; i++) {
Node z = new Node();
z.left = x = q.poll();
z.right = y = q.poll();
z.freq = x.freq + y.freq;
q.add(z);
}
return q.poll();
}
// This method builds the table for the compression and decompression
public static void buildTable(Node root) {
charToCode = new HashMap<Character, String>();
codeToChar = new HashMap<String, Character>();
postorder(root, new String());
}
// This method is used to traverse from ROOT-to-LEAVES
public static void postorder(Node n, String s) {
if(n == null)
return;
postorder(n.left, s+"0");
postorder(n.right, s+"1");
// Visit only nodes with keys
if (!Character.toString(n.alpha).equals("\0")){
System.out.println("{" + n.alpha + ":" + s + "}");
charToCode.put(n.alpha, s);
codeToChar.put(s, n.alpha);
}
}
//assuming tree and dictionary are already built...
public static String compress(String s) {
String c = new String();
for(int i = 0; i < s.length(); i++)
c = c + charToCode.get(s.charAt(i));
return c;
}
//assuming tree and dictionary are already built...
public static String decompress(String s) {
String temp = new String();
String result = new String();
for(int i = 0; i < s.length(); i++) {
temp = temp + s.charAt(i);
if(codeToChar.containsKey(temp)) {
result = result + codeToChar.get(temp);
temp = new String();
}
}
return result;
}
public static void saveToFile(String l) throws FileNotFoundException {
PrintWriter oFile = new PrintWriter("text.txt.huf");
oFile.print(charToCode.size());
for(char s : charToCode.keySet())
oFile.println("{" +s + ":" + charToCode.get(s)+ "}");
oFile.println(l);
oFile.close();
}
public static void writeToFile(String i) throws FileNotFoundException {
PrintWriter iFile = new PrintWriter("note.txt");
iFile.print(codeToChar.size());
for (String s : codeToChar.keySet())
iFile.println("{" +s + ":" + codeToChar.get(s)+ "}");
iFile.println(i);
iFile.close();
}
}
//Creating a Node Class
class Node {
public char alpha;
public int freq;
public Node left, right;
public Node(char a, int f) {
alpha = a;
freq = f;
}
public Node() {
}
public String toString() {
return alpha + " " + freq;
}
}
class FrequencyComparator implements Comparator<Node> {
public int compare(Node a, Node b) {
int freqA = a.freq;
int freqB = b.freq;
return freqA-freqB;
}
}
最佳答案
问题是,您将无法使用的代码存储在codeToChar
Character 0
值中,然后codeToChar.containsKey(temp)
方法中的decompress
条件为这些代码返回true
。
如果将&& codeToChar.get(temp)!=0
添加到条件中,它将可以正常工作。
该方法可以是:
public static String decompress(String s) {
String temp = new String();
String result = new String();
for(int i = 0; i < s.length(); i++) {
temp = temp + s.charAt(i);
Character c = codeToChar.get(temp);
if(c!=null && c!=0) {
result = result + c;
temp = "";
}
}
return result;
}
使用文本压缩为“ 1010111011111011000101101100011110000”的文本“ Lorem ipsum”进行了测试,并已解压缩。