我已经使用优先级队列在 Java 中实现了 Huffman 编码算法,其中我从根到叶遍历树,并根据符号在输入中出现的次数将编码示例设为 #=000011。一切都很好,树的构建很好,编码正如预期的那样:但是我得到的输出文件比原始文件大。我目前在遍历树的左节点和右节点时将“0”和“1”附加到字符串。可能我最终使用每个字符的所有 8 位,它对压缩没有帮助。我猜这些位需要转换为字符值。这样这些字符使用的位数少于 8,因此我得到了原始文件的压缩版本。您能否告诉我如何通过在 Java 中操作字符和减少位来实现压缩?谢谢
问问题
1980 次
1 回答
0
您可能正在使用 StringBuilder 并附加“0”或“1”,或者只是将+
“0”或“1”连接到字符串末尾的运算符。或者你正在使用某种OutputStream
并写入它。
您要做的是写入实际位。我建议在写之前先制作一个完整的字节。一个字节如下所示:
0x05
这将代表二进制字符串0000 0011
。
byte
您可以通过创建类型、添加和移动来制作这些:
public void writeToFile(String binaryString, OutputStream os){
int pos = 0;
while(pos < binaryString.length()){
byte nextByte = 0x00;
for(int i=0;i<8 && pos+i < binaryString.length(); i++){
nextByte << 1;
nextByte += binaryString.charAt(pos+i)=='0'?0x0:0x1;
}
os.write(nextByte);
pos+=8;
}
}
当然,一次写入一个字节是低效的,最重要的是,OutputStream 接口只接受字节数组(byte[]
)。所以你最好将字节存储在一个数组中(或者更简单, a List
),然后将它们写成更大的块。
如果您不允许使用字节写入(为什么不呢?ObjectOutputStream 支持写入字节数组!),那么您可以使用 Base64 对二进制字符串进行编码。但请记住,Base64 使您的数据使用量增加了 33%。
将字节数组转换为 base64 的一种简单方法是使用现有的编码器。添加以下导入后:
import sun.misc.BASE64Encoder;
您可以实例化编码器并将字节数组转换为字符串:
byte[] bytes = getBytesFromHuffmanEncoding();
BASE64Encoder encoder = new BASE64Encoder();
String encodedString = encoder.encode(bytes);
于 2011-10-18T01:52:26.997 回答