我正在写一个霍夫曼压缩/解压缩程序。我已经开始编写我的压缩方法而且卡住了。我试图读取文件中的所有字节,然后将所有字节放入一个字节数组。将所有字节放入字节数组后,我创建了一个int[]
数组,它将存储每个字节的所有频率(索引为ASCII码)。
它确实包含扩展的ASCII表,因为int
数组的大小是256.但是当我在文件中读取一个特殊字符时我会遇到问题(具有高于127的ASCII值的AKA字符) 。我理解一个字节是有符号的,并且一旦超过127个数字限制就会回绕到负值(并且数组索引显然不能为负)所以我试图通过在指定时将其转换为有符号值来对此进行计数我的数组索引(array[myByte&0xFF]
)。
这种方法有效,但是它给了我错误的ASCII值(例如,如果字符的正确ASCII值是134而我得到191或者其他东西)。更令人讨厌的部分是我注意到特殊字符被分成两个单独的字节,我觉得以后会引起问题(例如当我尝试解压缩时)。
如何使我的程序与每种类型的字符兼容(该程序应该能够压缩/解压缩图片,mp3等)。
也许我对此采取了错误的方法,但我不知道正确的方法是什么。请给我一些构建这个的提示。
树:
package CompPck;
import java.util.TreeMap;
abstract class Tree implements Comparable<Tree> {
public final int frequency; // the frequency of this tree
public Tree(int freq) { frequency = freq; }
// compares on the frequency
public int compareTo(Tree tree) {
return frequency - tree.frequency;
}
}
class Leaf extends Tree {
public final int value; // the character this leaf represents
public Leaf(int freq, int val) {
super(freq);
value = val;
}
}
class Node extends Tree {
public final Tree left, right; // subtrees
public Node(Tree l, Tree r) {
super(l.frequency + r.frequency);
left = l;
right = r;
}
}
构建树方法:
public static Tree buildTree(int[] charFreqs) {
PriorityQueue<Tree> trees = new PriorityQueue<Tree>();
for (int i = 0; i < charFreqs.length; i++){
if (charFreqs[i] > 0){
trees.offer(new Leaf(charFreqs[i], i));
}
}
//assert trees.size() > 0;
while (trees.size() > 1) {
Tree a = trees.poll();
Tree b = trees.poll();
trees.offer(new Node(a, b));
}
return trees.poll();
}
压缩方法:
public static void compress(File file){
try {
Path path = Paths.get(file.getAbsolutePath());
byte[] content = Files.readAllBytes(path);
TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
File nF = new File(file.getName() + "_comp");
nF.createNewFile();
BitFileWriter bfw = new BitFileWriter(nF);
int[] charFreqs = new int[256];
// read each byte and record the frequencies
for (byte b : content){
charFreqs[b&0xFF]++;
System.out.println(b&0xFF);
}
// build tree
Tree tree = buildTree(charFreqs);
// build TreeMap
fillEncodeMap(tree, new StringBuffer(), treeMap);
} catch (IOException e) {
e.printStackTrace();
}
}