huffman压缩 java_java代码采用哈夫曼实现压缩软件

本文详细介绍了如何使用Java实现哈夫曼编码进行文件压缩。通过读取每个字节的哈夫曼编码,将其转化为8位的二进制字符串,并处理非8的整数倍的编码,最终将所有编码写入压缩文件。解压缩过程则反向操作,读取编码长度和编码,还原文件。
摘要由CSDN通过智能技术生成

写出每一个字节所对应的编码

这一步较为复杂,因为JAVA

中没有自己定义的二进制为写入,我们就不得不将每 8 个 01 String

转化为一个 byte 再将 byte

写入。但是,问题又来了不是所有的 01String 都是

8

的整数倍,所以就又得在不是 8 整数倍的 String 后面补上

0

Java代码

/写入每一个字节所对应的 String编码

intcount=0;//记录中转的字符个数

inti=0;//第i个字节

String writes ="";

String tranString="";//中转字符串

String waiteString;//保存所转化的所有字符串

while((i<256)||(count>=8)){

//如果缓冲区的等待写入字符大于8

if(count>=8){

waiteString="";//清空要转化的的码

for(intt=0;t<8;t++){

waiteString=waiteString+writes.charAt(t);

}

//将writes前八位删掉

if(writes.length()>8){

tranString="";

for(intt=8;t

tranString=tranString+writes.charAt(t);

}

writes="";

writes=tranString;

}else{

writes="";

}

count=count-8;//写出一个8位的字节

intintw=changeString(waiteString);//得到String转化为int

//写入文件

fos.write(intw);

}else{

//得到地i个字节的编码信息,等待写入

count=count+SaveCode[i].n;

writes=writes+SaveCode[i].node;

i++;

}

}

//把所有编码没有足够8的整数倍的String补0使得足够8的整数倍,再写入

if(count>0){

waiteString="";//清空要转化的的码

for(intt=0;t<8;t++){

if(t

waiteString=waiteString+writes.charAt(t);

}else{

waiteString=waiteString+'0';

}

}

fos.write(changeString(waiteString));//写入

System.out.println("写入了->"+waiteString);

}

publicintchangeString(String s){

return((int)s.charAt(0)-48)*128+((int)s.charAt(1)-48)*64+((int)s.charAt(2)-48)*32

+((int)s.charAt(3)-48)*16+((int)s.charAt(4)-48)*8+((int)s.charAt(5)-48)*4

+((int)s.charAt(6)-48)*2+((int)s.charAt(7)-48);

}

/写入每一个字节所对应的 String编码

int count=0;//记录中转的字符个数

int i=0;//第i个字节

String writes ="";

String tranString="";//中转字符串

String waiteString;//保存所转化的所有字符串

while((i<256)||(count>=8)){

//如果缓冲区的等待写入字符大于8

if (count>=8){

waiteString="";//清空要转化的的码

for (int t=0;t<8;t++){

waiteString=waiteString+writes.charAt(t);

}

//将writes前八位删掉

if (writes.length()>8){

tranString="";

for (int t=8;t

tranString=tranString+writes.charAt(t);

}

writes="";

writes=tranString;

}else{

writes="";

}

count=count-8;//写出一个8位的字节

int intw=changeString(waiteString);//得到String转化为int

//写入文件

fos.write(intw);

}else{

//得到地i个字节的编码信息,等待写入

count=count+SaveCode[i].n;

writes=writes+SaveCode[i].node;

i++;

}

}

//把所有编码没有足够8的整数倍的String补0使得足够8的整数倍,再写入

if (count>0){

waiteString="";//清空要转化的的码

for (int t=0;t<8;t++){

if (t

waiteString=waiteString+writes.charAt(t);

}else{

waiteString=waiteString+'0';

}

}

fos.write(changeString(waiteString));//写入

System.out.println("写入了->"+waiteString);

}

public int changeString(String s){

return ((int)s.charAt(0)-48)*128+((int)s.charAt(1)-48)*64+((int)s.charAt(2)-48)*32

+((int)s.charAt(3)-48)*16+((int)s.charAt(4)-48)*8+((int)s.charAt(5)-48)*4

+((int)s.charAt(6)-48)*2+((int)s.charAt(7)-48);

}

将源文件中的所有byte

转化为 01

哈夫曼编码,写入压缩文件

这一步也比较复杂,原理同上一步,在SaveCode

中查找一个 byte 所对应的哈夫曼编码,不够

8

的整数倍的就不足,再写入。

值得注意的事,最后一定要写一个byte

表示,补了多少个 0 方便解压缩时的删除

0

Java代码

//再次读入文件的信息,对应每一个字节写入编码

count=0;

writes ="";

tranString="";

intidata=fis.read();

//文件没有读完的时候

while((fis.available()>0)||(count>=8)){

//如果缓冲区的等待写入字符大于8

if(count>=8){

waiteString="";//清空要转化的的码

for(intt=0;t<8;t++){

waiteString=waiteString+writes.charAt(t);

}

//将writes前八位删掉

if(writes.length()>8){

tranString="";

for(intt=8;t

tranString=tranString+writes.charAt(t);

}

writes="";

writes=tranString;

}else{

writes="";

}

count=count-8;//写出一个8位的字节

intintw=changeString(waiteString);

fos.write(intw);//写到文件中区

}else{

//读入idata字节,对应编码写出信息

count=count+SaveCode[idata].n;

writes=writes+SaveCode[idata].node;

idata=fis.read();

}

}

count=count+SaveCode[idata].n;

writes=writes+SaveCode[idata].node;

//把count剩下的写入

intendsint=0;

if(count>0){

waiteString="";//清空要转化的的码

for(intt=0;t<8;t++){

if(t

waiteString=waiteString+writes.charAt(t);

}else{

waiteString=waiteString+'0';

endsint++;

}

}

fos.write(changeString(waiteString));//写入所补的0

//再次读入文件的信息,对应每一个字节写入编码

count=0;

writes ="";

tranString="";

int idata=fis.read();

//文件没有读完的时候

while ((fis.available()>0)||(count>=8)){

//如果缓冲区的等待写入字符大于8

if (count>=8){

waiteString="";//清空要转化的的码

for (int t=0;t<8;t++){

waiteString=waiteString+writes.charAt(t);

}

//将writes前八位删掉

if (writes.length()>8){

tranString="";

for (int t=8;t

tranString=tranString+writes.charAt(t);

}

writes="";

writes=tranString;

}else{

writes="";

}

count=count-8;//写出一个8位的字节

int intw=changeString(waiteString);

fos.write(intw);//写到文件中区

}else{

//读入idata字节,对应编码写出信息

count=count+SaveCode[idata].n;

writes=writes+SaveCode[idata].node;

idata=fis.read();

}

}

count=count+SaveCode[idata].n;

writes=writes+SaveCode[idata].node;

//把count剩下的写入

int endsint=0;

if (count>0){

waiteString="";//清空要转化的的码

for (int t=0;t<8;t++){

if (t

waiteString=waiteString+writes.charAt(t);

}else{

waiteString=waiteString+'0';

endsint++;

}

}

fos.write(changeString(waiteString));//写入所补的0

如此一来,整个的压缩过程就完毕了。

解压缩过程:

与压缩过程刚好是反着来进行的,知道的存储的方式我们就反着来读取看看。

读入所有字节所对应的编码长度:

Java代码

//读入文件中的每一个编码的长度

for(inti=0;i<256;i++){

Code hC=newCode();

hC.n=fis.read();

hC.node="";

SaveCode[i]=hC;

}

//读入文件中的每一个编码的长度

for (int i=0;i<256;i++){

Code hC=new Code();

hC.n=fis.read();

hC.node="";

SaveCode[i]=hC;

}

读入每一个字节所对应的编码

Java代码

inti=0;

intcount=0;

String coms="";

//读SaveCode中0~256字节的的数据

while(i<256){

//当缓存区的编码长度比编码[i]的长度长的时候

if(coms.length()>=SaveCode[i].n){

for(intt=0;t

SaveCode[i].node=SaveCode[i].node+coms.charAt(t);

}

//把coms前这几位去掉

String coms2="";

for(intt=SaveCode[i].n;t

coms2=coms2+coms.charAt(t);

}

coms="";

coms=coms2;//累计的下一个编码,继续的使用

i++;

}else{

//如果已经没有写出的话,再度入一个byte转化为01 String

coms=coms+IntToString(fis.read());

}

}

int i=0;

int count=0;

String coms="";

//读SaveCode中0~256字节的的数据

while (i<256){

//当缓存区的编码长度比编码[i]的长度长的时候

if (coms.length()>=SaveCode[i].n){

for (int t=0;t

SaveCode[i].node=SaveCode[i].node+coms.charAt(t);

}

//把coms前这几位去掉

String coms2="";

for (int t=SaveCode[i].n;t

coms2=coms2+coms.charAt(t);

}

coms="";

coms=coms2;//累计的下一个编码,继续的使用

i++;

}else{

//如果已经没有写出的话,再度入一个byte转化为01 String

coms=coms+IntToString(fis.read());

}

}

读入文件的哈夫曼编码

得注意的事,前面我们又补0

的位,所以在我们读取的时候,记得把之前所补得东西,给删除掉就 OK 了。

Java代码

String rsrg;//存转换成的Sting

String compString="";//存要比较的字符串

//读入文件,写出文件

while(fis.available()>1){

if(search(compString)>=0){

intcint=search(compString);

fos.write(cint);

//删掉前n个数据

String compString2="";

for(intt=SaveCode[cint].n;t

compString2=compString2+compString.charAt(t);

}

compString="";

compString=compString2;

}else{//继续读入

compString=compString+IntToString(fis.read());

}

}

//处理最后一个字节

intcint=fis.read();

String compString2="";

for(intt=0;t

compString2=compString2+compString.charAt(t);

}

compString=compString2;

//删掉前n个数据

while(compString.length()>0){

intccint=search(compString);

fos.write(ccint);

compString2="";

for(intt=SaveCode[ccint].n;t

compString2=compString2+compString.charAt(t);

}

compString="";

compString=compString2;

}

String rsrg;//存转换成的Sting

String compString="";//存要比较的字符串

//读入文件,写出文件

while(fis.available()>1){

if (search(compString)>=0){

int cint=search(compString);

fos.write(cint);

//删掉前n个数据

String compString2="";

for (int t=SaveCode[cint].n;t

compString2=compString2+compString.charAt(t);

}

compString="";

compString=compString2;

}else{//继续读入

compString=compString+IntToString(fis.read());

}

}

//处理最后一个字节

int cint=fis.read();

String compString2="";

for (int t=0;t

compString2=compString2+compString.charAt(t);

}

compString=compString2;

//删掉前n个数据

while (compString.length()>0){

int ccint=search(compString);

fos.write(ccint);

compString2="";

for (int t=SaveCode[ccint].n;t

compString2=compString2+compString.charAt(t);

}

compString="";

compString=compString2;

}

如此而来,一个简单的小压缩软件就实现了。

本次的文件读写比较复杂,之前些的时候遇到了很多的困难,参考了很多前辈的思路和代码,今天终于完成了,我~内牛满面

因为没有对其做任何的优化压缩的效率比较低,时间比较长,个位大侠不要见笑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值