②
写出每一个字节所对应的编码
这一步较为复杂,因为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;
}
如此而来,一个简单的小压缩软件就实现了。
本次的文件读写比较复杂,之前些的时候遇到了很多的困难,参考了很多前辈的思路和代码,今天终于完成了,我~内牛满面
因为没有对其做任何的优化压缩的效率比较低,时间比较长,个位大侠不要见笑。