哈夫曼编码完成后如何在Java中写入文件

哈夫曼编码完成后如何在Java中写入文件,java,file,byte,huffman-code,Java,File,Byte,Huffman Code,我已经为哈夫曼编码实现了一个类。该类将解析一个输入文件并从中构建一个哈夫曼树,并创建一个映射,该映射将文件中出现的每个不同字符作为键,并将字符的哈夫曼代码作为其值 例如,让字符串“aravind_is_a_good_boy”成为文件中的唯一一行。当您构建哈夫曼树并为每个角色生成哈夫曼代码时,我们可以看到,对于角色“a”,哈夫曼代码是“101”,对于角色“r”,哈夫曼代码是“0101”,等等 我的目的是压缩文件。因此,我无法将字符串直接写入文件,该字符串是通过用哈夫曼代码替换每个字符创建的。因为,

我已经为哈夫曼编码实现了一个类。该类将解析一个输入文件并从中构建一个哈夫曼树,并创建一个映射,该映射将文件中出现的每个不同字符作为键,并将字符的哈夫曼代码作为其值

例如,让字符串“aravind_is_a_good_boy”成为文件中的唯一一行。当您构建哈夫曼树并为每个角色生成哈夫曼代码时,我们可以看到,对于角色“a”,哈夫曼代码是“101”,对于角色“r”,哈夫曼代码是“0101”,等等

我的目的是压缩文件。因此,我无法将字符串直接写入文件,该字符串是通过用哈夫曼代码替换每个字符创建的。因为,每个字符将被至少3个字符替换(每个“1”和“0”仍将作为字符而不是位写入文件)。所以我想我会以字节的形式将其写入文件,因为无法将位写入文件。但是,'a'和'r'都作为'5'写入文件中。这将在尝试解压缩文件时导致问题

这就是我将一系列位转换为字节的方式:

public byte[] compressString(String s, CharCodeHashMap map) {
        String byteString = "";
        byte[] byteArr = new byte[s.length()];
        int size = 0;
        for (int i = 0; i < s.length(); i++) {
            byteString += addPaddingZeros(map.getCompressedChar(s.charAt(i)));
            byteArr[size++] = new BigInteger(byteString, 2).toByteArray()[0];
            byteString = "";
        }

        return byteArr;
    }
public byte[]compressString(字符串s,CharCodeHashMap映射){
字符串byteString=“”;
byte[]byteArr=新字节[s.length()];
int size=0;
对于(int i=0;i
我尝试在每个哈希代码前加上“1”来解决这个问题。但是,当你构建一个哈夫曼树,读取一个文件时,一些字符将超过8位。然后,问题是
new biginger(byteString,2)。toByteArray()
在数组中会有多个元素。(例如,如果'v'有hashcode'11010001'和
new biginger(byteString,2)。toByteArray()
返回一个元素数组[0,-47]。)


有人能告诉我一种写入文件的方法吗?这样,文件将被压缩,同时,这些问题也会得到解决。

问题是现代操作系统中的文件被建模为可索引的字节序列1

因此,您需要的是一种编码方式,即您的文件表示的位数可能不是8的倍数。这意味着比特流大小不一定是文件大小(字节)乘以8

有多种解决方案:

  • 在文件开头为文件大小保留N个字节(以位为单位)。例如,保留4个字节允许您表示最多232位的文件大小
  • 在文件开头保留3位,以保持8模的位数。您可以使用它来决定要忽略文件最后一个字节中的多少位
  • 使用某种编码来表示流的结尾;e、 g.将其表示为正在编码的文本流中的字符
有没有一种不使用比特的方法来处理这个问题?阿福,不



1-在较低级别,文件表示为由多个字节组成的磁盘块序列。因此,从物理存储的角度来看,压缩已经很小(例如比磁盘块小)的文件并不能实现任何效果。类似地,当表示被建模为字节序列时,保存或不保存(比如)3位是无意义的。。。如果这就是你所关心的。

问题是现代操作系统中的文件被建模为可索引的字节序列1

因此,您需要的是一种编码方式,即您的文件表示的位数可能不是8的倍数。这意味着比特流大小不一定是文件大小(字节)乘以8

有多种解决方案:

  • 在文件开头为文件大小保留N个字节(以位为单位)。例如,保留4个字节允许您表示最多232位的文件大小
  • 在文件开头保留3位,以保持8模的位数。您可以使用它来决定要忽略文件最后一个字节中的多少位
  • 使用某种编码来表示流的结尾;e、 g.将其表示为正在编码的文本流中的字符
有没有一种不使用比特的方法来处理这个问题?阿福,不



1-在较低级别,文件表示为由多个字节组成的磁盘块序列。因此,从物理存储的角度来看,压缩已经很小(例如比磁盘块小)的文件并不能实现任何效果。类似地,当表示被建模为字节序列时,保存或不保存(比如)3位是无意义的。。。如果这正是您所关心的。

是的,您可以将位写入文件。事实上,您总是在向文件中写入位。唯一的问题是你一次写八位

您需要的是一个位缓冲区,比如一个32位无符号变量,您可以将位累积到其中。另一个整数跟踪位缓冲区中的位数。使用左移位和或(或加号)运算符将更多位放入位缓冲区,使用和和右移位运算符将其删除。每当位缓冲区中有八位或更多位时,就将这八位作为字节写入文件。最后,将剩余的位(如果有)作为最后一个字节写入文件

因此,要将值中的位添加到缓冲区:

bitBuffer |= value << bitCount;
bitcount += bits;
您需要确保在解码时,不会将最后一个字节中的填充位误认为是另一个代码。您可以发送消息前消息中的实际位数(或最后一个字节中的位数),也可以在字母表中添加一个符号作为结束-
while (bitCount >= 8) {
    writeByte(bitBuffer & 0xff);
    bitBuffer >>>= 8;
    bitCount -= 8;
}