package huffman;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;

import com.google.common.primitives.Ints;

/**
 * 利用哈夫曼编码实现文件解压缩的类
 * 
 * @author dongyunqi
 * @date 2018年7月30日下午3:09:00
 * @description
 */
public class DeConpress {
	// 每个编码的长度(还原得到)
	public int[] codelengths = new int[256];
	// 对应的哈夫曼编码值(还原得到)
	public String[] codeMap = new String[256];

	/*
	 * 解压思路: 1、读取文件里面的码表 2、得到码表 3、读取数据 4、还原数据
	 */

	public void decompress(String srcpath, String destpath) throws Exception {
		FileInputStream fis = new FileInputStream(srcpath);
		FileOutputStream fos = new FileOutputStream(destpath);
		int value;
		int codeLength = 0;
		String code = "";
		// 还原码表,还原每个位置哈夫曼编码长度信息
		for (int i = 0; i < codelengths.length; i++) {
			value = fis.read();
			codelengths[i] = value;
			codeLength += codelengths[i];
		}
		// 还原每个字符的哈弗码组成的完成字符串
		// 得到总长度
		// 将总长度除以8的到字节个数,(8个字节为单位的个数)
		int len = codeLength / 8;
		// 如果不是8的倍数,则字节个数加1(对应压缩补0的情况)
		if ((codeLength) % 8 != 0) {
			len++;
		}
		// 读取哈夫曼编码
		// System.out.println("codeLength:"+len);
		for (int i = 0; i < len; i++) {
			// 把读到的整数转换成二进制
			code += changeIntToString(fis.read());
		}
		// System.out.println("哈夫曼编码:"+code);
		// 获取每个字符对应的哈夫曼码值
		for (int i = 0; i < codeMap.length; i++) {
			// 如果第i个位置不为0 ,则说明第i个位置存储有哈夫曼编码
			if (codelengths[i] != 0) {
				// 将得到的一串哈夫曼编码按照长度分割分割
				String ss = code.substring(0, codelengths[i]);
				codeMap[i] = ss;
				code = code.substring(codelengths[i]);
			} else {
				// 为0则没有对应的哈夫曼编码
				codeMap[i] = "";
			}
		}
		// 读取压缩的文件内容
		String codeContent = "";
		while (fis.available() > 1) {
			codeContent += changeIntToString(fis.read());
		}
		// 读取最后一个
		value = fis.read();
		// 把最后补的0给去掉
		codeContent = codeContent.substring(0, codeContent.length() - value);
		for (int i = 0; i < codeContent.length(); i++) {
			String codecontent = codeContent.substring(0, i + 1);
			for (int j = 0; j < codeMap.length; j++) {
				if (codeMap[j].equals(codecontent)) {
					// System.out.println("截取的字符串:"+codecontent);
					fos.write(j);
					fos.flush();
					codeContent = codeContent.substring(i + 1);
					// System.out.println("截取后剩余编码长度:"+codeContent.length());
					// count=1;
					i = -1;
					break;
				}
			}
		}
		fos.close();
		fis.close();
	}

	// 十进制转二进制字符串
	public String changeIntToString(int value) {
		String s = "";
		for (int i = 0; i < 8; i++) {
			s = value % 2 + s;
			value = value / 2;
		}
		return s;
	}
}
最近下载更多
姓王  LV1 2021年12月2日
1358619424  LV1 2020年6月15日
Riedel27  LV1 2020年6月11日
chinese  LV1 2020年3月21日
zer012  LV1 2020年3月13日
3242592726  LV1 2020年1月9日
蛋哥哥99  LV1 2019年11月12日
yczhenshuai  LV1 2019年11月7日
pengqiang  LV2 2019年11月4日
andywahaha1  LV1 2019年10月29日
最近浏览更多
1383838438  LV1 2023年10月30日
1WQAQW1  LV2 2023年6月12日
deluser  LV3 2022年9月19日
whfuai  LV14 2022年7月27日
crosa_Don  LV18 2022年7月22日
小资李  LV13 2022年6月30日
wanglinddad  LV55 2022年4月22日
暂无贡献等级
lxdgp123 2021年12月23日
暂无贡献等级
姓王  LV1 2021年12月2日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友