霍夫曼:无法解压像“æ”、“ø”、“å”和“•”这样的字符
Huffman: Can't decompress characters like 'æ', 'ø', 'å' and '•'
我正在处理我的 Huffman 压缩(或者此时的解压),但我无法正确解压“æ”、“ø”、“å”和“•”等字符。字符'æ'被解压为两个符号'ᅢᆭ'。知道应该做什么吗?
编辑: 我认为这可能与 BufferedWriter 和 InputStream(以及其他)有关。我可能需要用 UTF-8 或其他方式读写?我该怎么做?
编辑 2::在一些求助热线的帮助下,我发现“ᅢ”和“ᆭ”作为单独的字符写入文件。 'ø' 是否大于 1 个字节,也许我假设每个字符在某处都是 1 个字节?
public static void decompressFile() throws IOException {
byte[] compressedBytes = //somecode
int[] frequencyTable = //somecode
HuffmanNode root = //some code
//Generating code table
String[] codeTable = new String[256];
Huffman.getCodeTable(codeTable, root, "");
DataInputStream inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream("[//thecompressedfile]"
BitInputStream bitInputStream = new BitInputStream(inputStream, compressedBytes.length);
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newFileName));
HuffmanNode node = root;
int bit;
while ((bit = bitInputStream.readBit()) != -1) {
//int bit = bitInputStream.readBit();
System.out.print(bit + "");
if (bit == 0) {
node = node.getLeft();
if (node.isLeaf()) {
bufferedWriter.write(node.getAByte());
node = root;
}
} else if (bit == 1) {
node = node.getRight();
if (node.isLeaf()) {
bufferedWriter.write(node.getAByte());
node = root;
}
}
}
bufferedWriter.close();
}
您使用 InputStream
读取并使用 Writer
写入。第一个用于读取二进制数据,第二个用于写入文本。当您调用 bufferedWriter.write(node.getAByte())
.
时,您正在进行隐式转换
换句话说,您将二进制数据解释为 ISO-8859-1,因为您基本上是将一个字节转换为 char
(技术上是 int
用于...奇怪的原因)。然后你用任何平台默认编码写回它。
这会弄乱您的文本,除非它碰巧是 ISO-8859-1 编码并且平台默认编码是相同的。
更好的方法是将其始终视为二进制数据(如果它真的是文本也没关系,只要您不关心解释您的文本代码,你似乎没有这样做)。由于霍夫曼编码作用于字节流,这也更符合您对数据所做的操作。
为此,将 Writer
替换为 OutputStream
(即 FileOutputStream
,出于性能原因可能包含在 BufferedOutputStream
中)。
我正在处理我的 Huffman 压缩(或者此时的解压),但我无法正确解压“æ”、“ø”、“å”和“•”等字符。字符'æ'被解压为两个符号'ᅢᆭ'。知道应该做什么吗?
编辑: 我认为这可能与 BufferedWriter 和 InputStream(以及其他)有关。我可能需要用 UTF-8 或其他方式读写?我该怎么做?
编辑 2::在一些求助热线的帮助下,我发现“ᅢ”和“ᆭ”作为单独的字符写入文件。 'ø' 是否大于 1 个字节,也许我假设每个字符在某处都是 1 个字节?
public static void decompressFile() throws IOException {
byte[] compressedBytes = //somecode
int[] frequencyTable = //somecode
HuffmanNode root = //some code
//Generating code table
String[] codeTable = new String[256];
Huffman.getCodeTable(codeTable, root, "");
DataInputStream inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream("[//thecompressedfile]"
BitInputStream bitInputStream = new BitInputStream(inputStream, compressedBytes.length);
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(newFileName));
HuffmanNode node = root;
int bit;
while ((bit = bitInputStream.readBit()) != -1) {
//int bit = bitInputStream.readBit();
System.out.print(bit + "");
if (bit == 0) {
node = node.getLeft();
if (node.isLeaf()) {
bufferedWriter.write(node.getAByte());
node = root;
}
} else if (bit == 1) {
node = node.getRight();
if (node.isLeaf()) {
bufferedWriter.write(node.getAByte());
node = root;
}
}
}
bufferedWriter.close();
}
您使用 InputStream
读取并使用 Writer
写入。第一个用于读取二进制数据,第二个用于写入文本。当您调用 bufferedWriter.write(node.getAByte())
.
换句话说,您将二进制数据解释为 ISO-8859-1,因为您基本上是将一个字节转换为 char
(技术上是 int
用于...奇怪的原因)。然后你用任何平台默认编码写回它。
这会弄乱您的文本,除非它碰巧是 ISO-8859-1 编码并且平台默认编码是相同的。
更好的方法是将其始终视为二进制数据(如果它真的是文本也没关系,只要您不关心解释您的文本代码,你似乎没有这样做)。由于霍夫曼编码作用于字节流,这也更符合您对数据所做的操作。
为此,将 Writer
替换为 OutputStream
(即 FileOutputStream
,出于性能原因可能包含在 BufferedOutputStream
中)。