|
已经实现了huffman的编码过程,但是不知道如何用编码方式对文件进行压缩.下面给出简单的代码。
对范例文件test.dat的压缩比例为:126byte/27byte
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class WriteBinary
{
//由huffman算法产生的编码表
String[] code = {"0", "10", "11"};
/**
* 测试函数
*@param args
*/
public static void main(String args[])
{
WriteBinary w = new WriteBinary();
try
{
w.write("test.dat", "test.hfm"); //将test.dat文件的内容进行编码写入test.hfm
System.out.println(w.read("test.hfm")); // 从压缩后的文件中还原出源文件的内容,并打印
} catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 对源文件进行编码,并写入目标文件
*@param from 需要进行编码的源文件
*@param to 目标文件
*@throws IOException
*/
public void write(String from, String to) throws IOException
{
File fromFile = new File(from);
Scanner scan = new Scanner(fromFile);
File f = new File(to);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(f));
while(scan.hasNextLine())
{
String line = scan.nextLine();
System.out.println(line);
//将文件中的所有字符用编码替换
//如果字符种类很多,应该将编码对应表存入数组转换,而不应该像下面一样硬编码
line = line.replace("a", code[0]);
line = line.replace("b", code[1]);
line = line.replace("c", code[2]);
System.out.println(line);
byte[] buf = new byte[line.length() / 7];
//将编号码的String进行转化,转化成 byte数组,并存入文件,除去符号位,每7位对应1byte
for(int i = 0; i * 7 + 7 <= line.length(); i ++)
buf = Byte.valueOf(line.substring(i * 7, i * 7 + 7), 2);
out.write(buf);
}
out.flush();
out.close();
scan.close();
}
/**
* 从编码后的文件中读取并解码,返回原文件的内容
*@param file 编码后的文件
*@return 源文件内容的字符串
*@throws IOException
*/
public String read(String file) throws IOException
{
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
StringBuffer resultStr = new StringBuffer(); //最终需要返回的结果
StringBuffer codeStr = new StringBuffer(); //需要解析的编码的字符串
byte[] buf = new byte[1];
//从文件中读出byte数组,并转化成二进制字符串
while(in.read(buf) != -1)
{
//把从文件中读取出的byte转化成二进制字符串
String bStr = Integer.toBinaryString(buf[0]);
StringBuffer temp = new StringBuffer();
//对二进制字符串补0,因为 Integer.toBinaryString方法转化成的二进制数会省略前面的若干个0
for(int j = 0; j < 7 - bStr.length(); j ++)
temp.append('0');
//将读取出并转化好的二进制字符串放入codeStr,留待下一步对其进行解码
codeStr.append(temp + bStr);
}
in.close();
//对上面转化成的二进制字符串进行解码
for(int i = 0; i < codeStr.length(); i ++)
{
//huffman解码过程
if(codeStr.charAt(i) == '0')
resultStr.append('a');
else
{
i++;
if(i >= codeStr.length())
break;
if(codeStr.charAt(i) == '0')
resultStr.append('b');
else
resultStr.append('c');
}
}
return new String(resultStr);
}
}
test.dat的内容
aaabbcaaabbcbaaaabbcaaabbcbaaaabbcaaabbcbaaaabbcaaabbcbaaaabbcaaabbcbaaaabbcaaabbcbaa
aabbcaaabbcbaaaabbcaaabbcbaaaabbcaaabbcba
ps:
给出的代码只能对转换成二进制后,二进制位为7的倍数的文件进行压缩,如果需要弥补这个问题,需要在编码后的文件头中写入源文件的大小,本程序为简便起见,未作处理 |
|