二叉树路径长度_哈夫曼树的构造_哈夫曼树路径长度(3)

电脑杂谈  发布时间:2017-02-21 02:25:08  来源:网络整理

解压缩总体思路:(怎么写进去的就要怎么读出来)

1、读取文件头信息:1)字符种类总数;

2)各字符信息:字符ASCII码,补零个数,占用byte数,编码

(在这过程中,需要把读到的编码转换成与码表中相同的编码)

3)文件末尾补零个数。

2、读取文件信息:读取每个字节转换成01串,前面补零成8位,

加到等待匹配的字符串后,与码表中的编码匹配,写入。

读到文件末尾将加上去的0去掉。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * 实现文件解压缩
 * @author 客
 *
 */
public class OpenTest {
	//文件输入输出流
	FileInputStream fis;
	FileOutputStream fos;
	//被解压缩文件路径
	static String path = "src\\lwq\\java\\HuffmanCode0729\\Untitled 2";
	//解压缩后的文件路径
	static String newPath = "src\\lwq\\java\\HuffmanCode0729\\Untitled 3";
	//存储文件头信息--即各个字符信息的数组
	HeadInfo[] head;
	//文件末尾补零的数
	int fileAddZero;
	//记录总共有多少个字符
	int codeNum;

	public static void main(String[] args) throws IOException{
		OpenTest opentest = new OpenTest();
		//读取文件头信息
		opentest.readHead(path);
		//读取文件内容并输出
		opentest.readFile(path,newPath);		
	}	
	/**
	 * 读取文件头信息,按写入的顺序依次读出:
	 * 1、字符种类总数,
	 * 2、字符ASCII码,编码末尾补零数,字符占字节数,编码
	 * 3、文件末尾补零数
	 * 
	 * @throws IOException 
	 */
	public void readHead(String path) throws IOException{
		fis = new FileInputStream(path);
		
		//读取字符种类总数
		codeNum = fis.read();
		System.out.println(codeNum);
		//实例化记录文件头信息的数组,数组长度为字符种类总数
		head = new HeadInfo[codeNum];
		System.out.println("ascii\t字节数\t补零数\t编码");
		//以字符种类总数作为循环限制条件,读取每个字符的编码细则
		for(int i=0;i<codeNum;i++){
			//创建文件头信息对象
			HeadInfo info = new HeadInfo();
			
			//读取字符ASCII码,给对象设置ASCII码
			info.setAscii(fis.read());
			System.out.print(info.getAscii()+"\t"+(char)info.getAscii()+"  ");
			
			//读取编码末尾补零数,并给对象设置
			info.setZeroNum(fis.read());
			
			//读取编码所占字节数,给对象设置
			info.setByteNum(fis.read());
			System.out.print(info.getByteNum()+"\t");
			
			//读取当前编码的每个字节
			for(int j=0;j<info.getByteNum();j++){
				int code_int = fis.read();
				//读取到的整数转换成String---0,1串,该01串不会以0开头
				String code_string = Integer.toBinaryString(code_int);
//				System.out.println("s++"+code_string);
				int length = code_string.length();
				//01串不足8位的在前面补零
				if(length%8!=0){
					for(int k=0;k<8-length;k++){
						code_string = '0'+code_string;						
					}
				}
				//给info对象设置编码,含补零,每个字节的前面补零的01串相加
				info.setCode(info.getCode()+code_string);				
			}
			//得到完整的补零后的01串,即文件头信息存储的编码
			System.out.print(info.getZeroNum()+"\t");
			
			//根据编码末尾补零个数,恢复编码不补零的编码,即码表中存储的编码,
			for(int t=0;t<info.getZeroNum();t++){
				info.setCode(info.getCode().substring(0, info.getCode().length()-1));
			}
			System.out.println("去0后  "+info.getCode());	
			//将info对象添加到数组中
			head[i] = info;
		}
		//读取头信息的最后一个内容:文章末尾的补零的个数
		fileAddZero = fis.read();
		System.out.println("文件末尾补零"+fileAddZero);		
	}	
	/**
	 * 读取文件内容,写入新文件,完成解压缩
	 * @throws IOException 
	 */
	public void readFile(String path,String newPath) throws IOException{
		fos = new FileOutputStream(newPath);
		//等待转换的字符串
		String str = "";
		//当文件可读信息大于零时
		while(fis.available()>0){
			//读取一个字节,赋值给整数txt
			int txt = fis.read();
			//将该整数转换成01串,该字符串不会以0开头
			String temp = Integer.toBinaryString(txt);
			System.out.println(temp+"   nnnn");
			
			//给转换成的01串,前面补零成完整的8位的字符串
			int frontAddZero = temp.length()%8;
			if(frontAddZero!=0){
				for(int i=0;i<8-frontAddZero;i++){
					temp = '0'+temp;				
				}
			}
			System.out.println(temp+">>>>>>>>>>>>");
			//加到等待转换的字符串后,等待转换
			str = str+temp;
			System.out.println(str+" !!!!等待转换!!!!");
		
			for(int j=0;j<codeNum;j++){
				//判断当前等待转换的字符串,是否以码表中的某个编码开头
				if(str.startsWith((head[j].getCode()))){
					//如果是,写入这个编码对应的字符
					System.out.println(str+"  ========  "+head[j].getCode());						
//					System.out.println("qqqq"+i);
					System.out.println((char)head[j].getAscii());
					fos.write(head[j].getAscii());
//					
					//将等待转换的字符串去掉已经写入的编码部分
					String tran = str;
					str = "";
					for(int k=head[j].getCode().length();k<tran.length();k++){
						str = str+tran.charAt(k);
					}
					//设置循环从头开始判断现在的str是否以某编码开头
					j = -1;
					//如果此时已经没有可读的文件信息了
					if(fis.available()==0){
						//将文件末尾添加的0的个数,在str中删去
						String tra = str;
						str = "";
						for(int t=0;t<tra.length()-fileAddZero;t++){
							str = str+tra.charAt(t);
						}
						//如果删去之后字符串空了,那么跳出循环,文件读取完毕
						if(str==""){
							break;
						}
						//如果str不为空,那么继续j=-1的地方循环判断是否以某编码开头
					}
				}			
			}//for循环	
		}//while循环
		//确认文件读取完毕
		System.out.println(str.length()+" 最后str的长度");
	}		
}


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-33591-3.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...